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:
Diffstat (limited to 'source/blender/editors/curve/editcurve.c')
-rw-r--r--source/blender/editors/curve/editcurve.c1037
1 files changed, 767 insertions, 270 deletions
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 2d68d19c589..90bec418e0e 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -43,15 +43,9 @@
#include "BLI_dynstr.h"
#include "BLI_rand.h"
-#include "DNA_curve_types.h"
#include "DNA_key_types.h"
-#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_curve.h"
@@ -68,8 +62,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "ED_anim_api.h"
-#include "ED_curve.h"
#include "ED_keyframes_edit.h"
#include "ED_object.h"
#include "ED_screen.h"
@@ -83,6 +75,12 @@
#include "RNA_access.h"
#include "RNA_define.h"
+/* Undo stuff */
+typedef struct {
+ ListBase nubase;
+ void *lastsel;
+} UndoCurve;
+
void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus);
static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus);
@@ -332,7 +330,7 @@ void make_editNurb(Object *obedit)
editnurb= cu->editnurb= MEM_callocN(sizeof(ListBase), "editnurb");
nu= cu->nurb.first;
- cu->lastselbp= NULL; /* for select row */
+ cu->lastsel= NULL; /* for select row */
while(nu) {
newnu= duplicateNurb(nu);
@@ -397,6 +395,8 @@ void CU_select_swap(Object *obedit)
BezTriple *bezt;
int a;
+ cu->lastsel= NULL;
+
for(nu= editnurb->first; nu; nu= nu->next) {
if(nu->type == CU_BEZIER) {
bezt= nu->bezt;
@@ -504,8 +504,8 @@ void CURVE_OT_separate(wmOperatorType *ot)
static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
{
/* return u!=-1: 1 row in u-direction selected. U has value between 0-pntsv
- * return v!=-1: 1 collumn in v-direction selected. V has value between 0-pntsu
- */
+ * return v!=-1: 1 collumn in v-direction selected. V has value between 0-pntsu
+ */
BPoint *bp;
int a, b, sel;
@@ -610,9 +610,9 @@ static void translateflagNurb(ListBase *editnurb, short flag, float *vec)
a= nu->pntsu;
bezt= nu->bezt;
while(a--) {
- if(bezt->f1 & flag) add_v3_v3v3(bezt->vec[0], bezt->vec[0], vec);
- if(bezt->f2 & flag) add_v3_v3v3(bezt->vec[1], bezt->vec[1], vec);
- if(bezt->f3 & flag) add_v3_v3v3(bezt->vec[2], bezt->vec[2], vec);
+ if(bezt->f1 & flag) add_v3_v3(bezt->vec[0], vec);
+ if(bezt->f2 & flag) add_v3_v3(bezt->vec[1], vec);
+ if(bezt->f3 & flag) add_v3_v3(bezt->vec[2], vec);
bezt++;
}
}
@@ -620,7 +620,7 @@ static void translateflagNurb(ListBase *editnurb, short flag, float *vec)
a= nu->pntsu*nu->pntsv;
bp= nu->bp;
while(a--) {
- if(bp->f1 & flag) add_v3_v3v3(bp->vec, bp->vec, vec);
+ if(bp->f1 & flag) add_v3_v3(bp->vec, vec);
bp++;
}
}
@@ -662,7 +662,7 @@ static int deleteflagNurb(bContext *C, wmOperator *op, int flag)
if(obedit && obedit->type==OB_SURF);
else return OPERATOR_CANCELLED;
- cu->lastselbp= NULL;
+ cu->lastsel= NULL;
nu= editnurb->first;
while(nu) {
@@ -895,9 +895,12 @@ static void adduplicateflagNurb(Object *obedit, short flag)
Nurb *nu, *newnu;
BezTriple *bezt, *bezt1;
BPoint *bp, *bp1;
+ Curve *cu= (Curve*)obedit->data;
int a, b, starta, enda, newu, newv;
char *usel;
+ cu->lastsel= NULL;
+
nu= editnurb->last;
while(nu) {
if(nu->type == CU_BEZIER) {
@@ -929,9 +932,9 @@ static void adduplicateflagNurb(Object *obedit, short flag)
bezt1++;
}
- if(nu->flagu & CU_CYCLIC) {
+ if(nu->flagu & CU_NURB_CYCLIC) {
if(starta!=0 || enda!=nu->pntsu-1) {
- newnu->flagu &= ~CU_CYCLIC;
+ newnu->flagu &= ~CU_NURB_CYCLIC;
}
}
}
@@ -966,9 +969,9 @@ static void adduplicateflagNurb(Object *obedit, short flag)
bp1++;
}
- if(nu->flagu & CU_CYCLIC) {
+ if(nu->flagu & CU_NURB_CYCLIC) {
if(starta!=0 || enda!=nu->pntsu-1) {
- newnu->flagu &= ~CU_CYCLIC;
+ newnu->flagu &= ~CU_NURB_CYCLIC;
}
}
@@ -1507,11 +1510,15 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu
Nurb *nu;
BPoint *bp;
BezTriple *bezt;
+ Curve *cu;
int a;
short sel;
-
+
if(obedit==0) return;
-
+
+ cu= (Curve*)obedit->data;
+ cu->lastsel= NULL;
+
for(nu= editnurb->first; nu; nu= nu->next) {
sel= 0;
if(nu->type == CU_BEZIER) {
@@ -1827,6 +1834,8 @@ static int select_inverse_exec(bContext *C, wmOperator *op)
BezTriple *bezt;
int a;
+ cu->lastsel= NULL;
+
for(nu= editnurb->first; nu; nu= nu->next) {
if(nu->type == CU_BEZIER) {
bezt= nu->bezt;
@@ -1882,29 +1891,29 @@ void CURVE_OT_select_inverse(wmOperatorType *ot)
* @param None
*/
-static int subdivide_exec(bContext *C, wmOperator *op)
+static void subdividenurb(Object *obedit, int number_cuts)
{
- Object *obedit= CTX_data_edit_object(C);
Curve *cu= obedit->data;
ListBase *editnurb= curve_get_editcurve(obedit);
Nurb *nu;
BezTriple *prevbezt, *bezt, *beztnew, *beztn;
BPoint *bp, *prevbp, *bpnew, *bpn;
float vec[15];
- int a, b, sel, amount, *usel, *vsel;
+ int a, b, sel, amount, *usel, *vsel, i;
+ float factor;
// printf("*** subdivideNurb: entering subdivide\n");
for(nu= editnurb->first; nu; nu= nu->next) {
amount= 0;
if(nu->type == CU_BEZIER) {
- /*
- Insert a point into a 2D Bezier curve.
- Endpoints are preserved. Otherwise, all selected and inserted points are
- newly created. Old points are discarded.
- */
+ /*
+ Insert a point into a 2D Bezier curve.
+ Endpoints are preserved. Otherwise, all selected and inserted points are
+ newly created. Old points are discarded.
+ */
/* count */
- if(nu->flagu & CU_CYCLIC) {
+ if(nu->flagu & CU_NURB_CYCLIC) {
a= nu->pntsu;
bezt= nu->bezt;
prevbezt= bezt+(a-1);
@@ -1915,7 +1924,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
bezt= prevbezt+1;
}
while(a--) {
- if( BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) amount++;
+ if( BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) amount+=number_cuts;
prevbezt= bezt;
bezt++;
}
@@ -1925,7 +1934,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
beztnew =
(BezTriple*)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
beztn= beztnew;
- if(nu->flagu & CU_CYCLIC) {
+ if(nu->flagu & CU_NURB_CYCLIC) {
a= nu->pntsu;
bezt= nu->bezt;
prevbezt= bezt+(a-1);
@@ -1940,37 +1949,46 @@ static int subdivide_exec(bContext *C, wmOperator *op)
beztn++;
if( BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) {
- memcpy(beztn, bezt, sizeof(BezTriple));
-
- /* midpoint subdividing */
- mid_v3_v3v3(vec, prevbezt->vec[1], prevbezt->vec[2]);
- mid_v3_v3v3(vec+3, prevbezt->vec[2], bezt->vec[0]);
- mid_v3_v3v3(vec+6, bezt->vec[0], bezt->vec[1]);
-
- mid_v3_v3v3(vec+9, vec, vec+3);
- mid_v3_v3v3(vec+12, vec+3, vec+6);
-
- /* change handle of prev beztn */
- VECCOPY((beztn-1)->vec[2], vec);
- /* new point */
- VECCOPY(beztn->vec[0], vec+9);
- mid_v3_v3v3(beztn->vec[1], vec+9, vec+12);
- VECCOPY(beztn->vec[2], vec+12);
- /* handle of next bezt */
- if(a==0 && (nu->flagu & CU_CYCLIC)) {VECCOPY(beztnew->vec[0], vec+6);}
- else {VECCOPY(bezt->vec[0], vec+6);}
-
- beztn->radius = (prevbezt->radius + bezt->radius)/2.0f;
- beztn->weight = (prevbezt->weight + bezt->weight)/2.0f;
-
- beztn++;
+ float prevvec[3][3];
+
+ memcpy(prevvec, prevbezt->vec, sizeof(float) * 9);
+
+ for (i = 0; i < number_cuts; i++) {
+ factor = 1.0f / (number_cuts + 1 - i);
+
+ memcpy(beztn, bezt, sizeof(BezTriple));
+
+ /* midpoint subdividing */
+ interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor);
+ interp_v3_v3v3(vec+3, prevvec[2], bezt->vec[0], factor);
+ interp_v3_v3v3(vec+6, bezt->vec[0], bezt->vec[1], factor);
+
+ interp_v3_v3v3(vec+9, vec, vec+3, factor);
+ interp_v3_v3v3(vec+12, vec+3, vec+6, factor);
+
+ /* change handle of prev beztn */
+ VECCOPY((beztn-1)->vec[2], vec);
+ /* new point */
+ VECCOPY(beztn->vec[0], vec+9);
+ interp_v3_v3v3(beztn->vec[1], vec+9, vec+12, factor);
+ VECCOPY(beztn->vec[2], vec+12);
+ /* handle of next bezt */
+ if(a==0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) {VECCOPY(beztnew->vec[0], vec+6);}
+ else {VECCOPY(bezt->vec[0], vec+6);}
+
+ beztn->radius = (prevbezt->radius + bezt->radius)/2;
+ beztn->weight = (prevbezt->weight + bezt->weight)/2;
+
+ memcpy(prevvec, beztn->vec, sizeof(float) * 9);
+ beztn++;
+ }
}
prevbezt= bezt;
bezt++;
}
/* last point */
- if((nu->flagu & CU_CYCLIC)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
+ if((nu->flagu & CU_NURB_CYCLIC)==0) memcpy(beztn, prevbezt, sizeof(BezTriple));
MEM_freeN(nu->bezt);
nu->bezt= beztnew;
@@ -1980,14 +1998,14 @@ static int subdivide_exec(bContext *C, wmOperator *op)
}
} /* End of 'if(nu->type == CU_BEZIER)' */
else if (nu->pntsv==1) {
- /*
- All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
- are handled together with the regular NURB plane division, as it
- should be. I split it off just now, let's see if it is
- stable... nzc 30-5-'00
- */
+ /*
+ All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
+ are handled together with the regular NURB plane division, as it
+ should be. I split it off just now, let's see if it is
+ stable... nzc 30-5-'00
+ */
/* count */
- if(nu->flagu & CU_CYCLIC) {
+ if(nu->flagu & CU_NURB_CYCLIC) {
a= nu->pntsu;
bp= nu->bp;
prevbp= bp+(a-1);
@@ -1998,7 +2016,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
bp= prevbp+1;
}
while(a--) {
- if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) amount++;
+ if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) amount+=number_cuts;
prevbp= bp;
bp++;
}
@@ -2009,7 +2027,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
(BPoint*)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
bpn= bpnew;
- if(nu->flagu & CU_CYCLIC) {
+ if(nu->flagu & CU_NURB_CYCLIC) {
a= nu->pntsu;
bp= nu->bp;
prevbp= bp+(a-1);
@@ -2024,19 +2042,20 @@ static int subdivide_exec(bContext *C, wmOperator *op)
bpn++;
if( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) {
- // printf("*** subdivideNurb: insert 'linear' point\n");
- memcpy(bpn, bp, sizeof(BPoint));
- bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
- bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
- bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
- bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
- bpn++;
+ // printf("*** subdivideNurb: insert 'linear' point\n");
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+
+ memcpy(bpn, bp, sizeof(BPoint));
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ bpn++;
+ }
}
prevbp= bp;
bp++;
}
- if((nu->flagu & CU_CYCLIC)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* last point */
+ if((nu->flagu & CU_NURB_CYCLIC)==0) memcpy(bpn, prevbp, sizeof(BPoint)); /* last point */
MEM_freeN(nu->bp);
nu->bp= bpnew;
@@ -2048,54 +2067,54 @@ static int subdivide_exec(bContext *C, wmOperator *op)
}
} /* End of 'else if(nu->pntsv==1)' */
else if(nu->type == CU_NURBS) {
- /* This is a very strange test ... */
- /**
- Subdivide NURB surfaces - nzc 30-5-'00 -
+ /* This is a very strange test ... */
+ /**
+ Subdivide NURB surfaces - nzc 30-5-'00 -
- Subdivision of a NURB curve can be effected by adding a
- control point (insertion of a knot), or by raising the
- degree of the functions used to build the NURB. The
- expression
-
- degree = #knots - #controlpoints + 1 (J Walter piece)
- degree = #knots - #controlpoints (Blender
- implementation)
- ( this is confusing.... what is true? Another concern
- is that the JW piece allows the curve to become
- explicitly 1st order derivative discontinuous, while
- this is not what we want here... )
-
- is an invariant for a single NURB curve. Raising the degree
- of the NURB is done elsewhere; the degree is assumed
- constant during this opration. Degree is a property shared
- by all controlpoints in a curve (even though it is stored
- per control point - this can be misleading).
- Adding a knot is done by searching for the place in the
- knot vector where a certain knot value must be inserted, or
- by picking an appropriate knot value between two existing
- ones. The number of controlpoints that is influenced by the
- insertion depends on the order of the curve. A certain
- minimum number of knots is needed to form high-order
- curves, as can be seen from the equation above. In Blender,
- currently NURBs may be up to 6th order, so we modify at
- most 6 points. One point is added. For an n-degree curve,
- n points are discarded, and n+1 points inserted
- (so effectively, n points are modified). (that holds for
- the JW piece, but it seems not for our NURBs)
- In practice, the knot spacing is copied, but the tail
- (the points following the insertion point) need to be
- offset to keep the knot series ascending. The knot series
- is always a series of monotonically ascending integers in
- Blender. When not enough control points are available to
- fit the order, duplicates of the endpoints are added as
- needed.
- */
+ Subdivision of a NURB curve can be effected by adding a
+ control point (insertion of a knot), or by raising the
+ degree of the functions used to build the NURB. The
+ expression
+
+ degree = #knots - #controlpoints + 1 (J Walter piece)
+ degree = #knots - #controlpoints (Blender
+ implementation)
+ ( this is confusing.... what is true? Another concern
+ is that the JW piece allows the curve to become
+ explicitly 1st order derivative discontinuous, while
+ this is not what we want here... )
+
+ is an invariant for a single NURB curve. Raising the degree
+ of the NURB is done elsewhere; the degree is assumed
+ constant during this opration. Degree is a property shared
+ by all controlpoints in a curve (even though it is stored
+ per control point - this can be misleading).
+ Adding a knot is done by searching for the place in the
+ knot vector where a certain knot value must be inserted, or
+ by picking an appropriate knot value between two existing
+ ones. The number of controlpoints that is influenced by the
+ insertion depends on the order of the curve. A certain
+ minimum number of knots is needed to form high-order
+ curves, as can be seen from the equation above. In Blender,
+ currently NURBs may be up to 6th order, so we modify at
+ most 6 points. One point is added. For an n-degree curve,
+ n points are discarded, and n+1 points inserted
+ (so effectively, n points are modified). (that holds for
+ the JW piece, but it seems not for our NURBs)
+ In practice, the knot spacing is copied, but the tail
+ (the points following the insertion point) need to be
+ offset to keep the knot series ascending. The knot series
+ is always a series of monotonically ascending integers in
+ Blender. When not enough control points are available to
+ fit the order, duplicates of the endpoints are added as
+ needed.
+ */
/* selection-arrays */
usel= MEM_callocN(sizeof(int)*nu->pntsu, "subivideNurb3");
vsel= MEM_callocN(sizeof(int)*nu->pntsv, "subivideNurb3");
sel= 0;
- /* Count the number of selected points. */
+ /* Count the number of selected points. */
bp= nu->bp;
for(a=0; a<nu->pntsv; a++) {
for(b=0; b<nu->pntsu; b++) {
@@ -2108,9 +2127,16 @@ static int subdivide_exec(bContext *C, wmOperator *op)
}
}
if( sel == (nu->pntsu*nu->pntsv) ) { /* subdivide entire nurb */
- /* Global subdivision is a special case of partial
- subdivision. Strange it is considered separately... */
- bpn=bpnew= MEM_mallocN( (2*nu->pntsu-1)*(2*nu->pntsv-1)*sizeof(BPoint), "subdivideNurb4");
+ /* Global subdivision is a special case of partial
+ subdivision. Strange it is considered separately... */
+
+ /* count of nodes (after subdivision) along U axis */
+ int countu= nu->pntsu + (nu->pntsu - 1) * number_cuts;
+
+ /* total count of nodes after subdivision */
+ int tot= ((number_cuts+1)*nu->pntsu-number_cuts)*((number_cuts+1)*nu->pntsv-number_cuts);
+
+ bpn=bpnew= MEM_mallocN( tot*sizeof(BPoint), "subdivideNurb4");
bp= nu->bp;
/* first subdivide rows */
for(a=0; a<nu->pntsv; a++) {
@@ -2119,41 +2145,43 @@ static int subdivide_exec(bContext *C, wmOperator *op)
bpn++;
bp++;
if(b<nu->pntsu-1) {
- *bpn= *bp;
prevbp= bp-1;
- bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
- bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
- bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
- bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
- bpn++;
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ *bpn= *bp;
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ bpn++;
+ }
}
}
- bpn+= (2*nu->pntsu-1);
+ bpn+= number_cuts * countu;
}
/* now insert new */
- bpn= bpnew+(2*nu->pntsu-1);
- bp= bpnew+(4*nu->pntsu-2);
+ bpn= bpnew+((number_cuts+1)*nu->pntsu - number_cuts);
+ bp= bpnew+(number_cuts+1)*((number_cuts+1)*nu->pntsu-number_cuts);
prevbp= bpnew;
for(a=1; a<nu->pntsv; a++) {
- for(b=0; b<2*nu->pntsu-1; b++) {
- *bpn= *bp;
- bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
- bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
- bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
- bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
- bpn++;
+ for(b=0; b<(number_cuts+1)*nu->pntsu-number_cuts; b++) {
+ BPoint *tmp= bpn;
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ *tmp= *bp;
+ interp_v4_v4v4(tmp->vec, prevbp->vec, bp->vec, factor);
+ tmp += countu;
+ }
bp++;
prevbp++;
+ bpn++;
}
- bp+= (2*nu->pntsu-1);
- bpn+= (2*nu->pntsu-1);
- prevbp+= (2*nu->pntsu-1);
+ bp+= number_cuts * countu;
+ bpn+= number_cuts * countu;
+ prevbp+= number_cuts * countu;
}
MEM_freeN(nu->bp);
nu->bp= bpnew;
- nu->pntsu= 2*nu->pntsu-1;
- nu->pntsv= 2*nu->pntsv-1;
+ nu->pntsu= (number_cuts+1)*nu->pntsu-number_cuts;
+ nu->pntsv= (number_cuts+1)*nu->pntsv-number_cuts;
makeknots(nu, 1);
makeknots(nu, 2);
} /* End of 'if(sel== nu->pntsu*nu->pntsv)' (subdivide entire NURB) */
@@ -2161,7 +2189,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
/* subdivide in v direction? */
sel= 0;
for(a=0; a<nu->pntsv-1; a++) {
- if(vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu) sel++;
+ if(vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu) sel+=number_cuts;
}
if(sel) { /* V ! */
@@ -2170,29 +2198,30 @@ static int subdivide_exec(bContext *C, wmOperator *op)
for(a=0; a<nu->pntsv; a++) {
for(b=0; b<nu->pntsu; b++) {
*bpn= *bp;
- bpn++;
+ bpn++;
bp++;
}
if( (a<nu->pntsv-1) && vsel[a]==nu->pntsu && vsel[a+1]==nu->pntsu ) {
- prevbp= bp- nu->pntsu;
- for(b=0; b<nu->pntsu; b++) {
- /*
- This simple bisection must be replaces by a
- subtle resampling of a number of points. Our
- task is made slightly easier because each
- point in our curve is a separate data
- node. (is it?)
- */
- *bpn= *prevbp;
- bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
- bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
- bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
- bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
- bpn++;
- prevbp++;
- bp++;
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
+ prevbp= bp- nu->pntsu;
+ for(b=0; b<nu->pntsu; b++) {
+ /*
+ This simple bisection must be replaces by a
+ subtle resampling of a number of points. Our
+ task is made slightly easier because each
+ point in our curve is a separate data
+ node. (is it?)
+ */
+ *bpn= *prevbp;
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ bpn++;
+
+ prevbp++;
+ bp++;
+ }
+ bp-= nu->pntsu;
}
- bp-= nu->pntsu;
}
}
MEM_freeN(nu->bp);
@@ -2204,12 +2233,12 @@ static int subdivide_exec(bContext *C, wmOperator *op)
/* or in u direction? */
sel= 0;
for(a=0; a<nu->pntsu-1; a++) {
- if(usel[a]==nu->pntsv && usel[a+1]==nu->pntsv) sel++;
+ if(usel[a]==nu->pntsv && usel[a+1]==nu->pntsv) sel+=number_cuts;
}
if(sel) { /* U ! */
- /* Inserting U points is sort of 'default' Flat curves only get */
- /* U points inserted in them. */
+ /* Inserting U points is sort of 'default' Flat curves only get */
+ /* U points inserted in them. */
bpn=bpnew= MEM_mallocN( (sel+nu->pntsu)*nu->pntsv*sizeof(BPoint), "subdivideNurb4");
bp= nu->bp;
for(a=0; a<nu->pntsv; a++) {
@@ -2218,20 +2247,20 @@ static int subdivide_exec(bContext *C, wmOperator *op)
bpn++;
bp++;
if( (b<nu->pntsu-1) && usel[b]==nu->pntsv && usel[b+1]==nu->pntsv ) {
- /*
- One thing that bugs me here is that the
- orders of things are not the same as in
- the JW piece. Also, this implies that we
- handle at most 3rd order curves? I miss
- some symmetry here...
- */
+ /*
+ One thing that bugs me here is that the
+ orders of things are not the same as in
+ the JW piece. Also, this implies that we
+ handle at most 3rd order curves? I miss
+ some symmetry here...
+ */
+ for (i = 0; i < number_cuts; i++) {
+ factor = (float)(i + 1) / (number_cuts + 1);
prevbp= bp- 1;
*bpn= *prevbp;
- bpn->vec[0]= (prevbp->vec[0]+bp->vec[0])/2.0;
- bpn->vec[1]= (prevbp->vec[1]+bp->vec[1])/2.0;
- bpn->vec[2]= (prevbp->vec[2]+bp->vec[2])/2.0;
- bpn->vec[3]= (prevbp->vec[3]+bp->vec[3])/2.0;
+ interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
bpn++;
+ }
}
}
}
@@ -2239,7 +2268,7 @@ static int subdivide_exec(bContext *C, wmOperator *op)
nu->bp= bpnew;
nu->pntsu+= sel;
makeknots(nu, 1); /* shift knots
- forward */
+ forward */
}
}
}
@@ -2248,6 +2277,14 @@ static int subdivide_exec(bContext *C, wmOperator *op)
} /* End of 'if(nu->type == CU_NURBS)' */
}
+}
+
+static int subdivide_exec(bContext *C, wmOperator *op)
+{
+ Object *obedit= CTX_data_edit_object(C);
+ int number_cuts= RNA_int_get(op->ptr, "number_cuts");
+
+ subdividenurb(obedit, number_cuts);
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
@@ -2267,6 +2304,8 @@ void CURVE_OT_subdivide(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "number_cuts", 1, 1, 100, "Number of cuts", "", 1, 100);
}
/******************** find nearest ************************/
@@ -2423,8 +2462,8 @@ static int convertspline(short type, Nurb *nu)
else if(type==CU_NURBS) {
nu->type = CU_NURBS;
nu->orderu= 4;
- nu->flagu &= CU_CYCLIC; /* disable all flags except for cyclic */
- nu->flagu += 4;
+ nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
+ nu->flagu |= CU_NURB_BEZIER;
makeknots(nu, 1);
a= nu->pntsu*nu->pntsv;
bp= nu->bp;
@@ -2473,11 +2512,11 @@ static int convertspline(short type, Nurb *nu)
nu->orderu= 4;
nu->orderv= 1;
nu->type = type;
- if(nu->flagu & CU_CYCLIC) c= nu->orderu-1;
+ if(nu->flagu & CU_NURB_CYCLIC) c= nu->orderu-1;
else c= 0;
if(type== CU_NURBS) {
- nu->flagu &= CU_CYCLIC; /* disable all flags except for cyclic */
- nu->flagu += 4;
+ nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */
+ nu->flagu |= CU_NURB_BEZIER;
makeknots(nu, 1);
}
}
@@ -2737,7 +2776,7 @@ static void make_selection_list_nurb(ListBase *editnurb)
bp= nu->bp;
a= nu->pntsu;
while(a--) {
- add_v3_v3v3(nus->vec, nus->vec, bp->vec);
+ add_v3_v3(nus->vec, bp->vec);
bp++;
}
mul_v3_fl(nus->vec, 1.0/(float)nu->pntsu);
@@ -2798,6 +2837,10 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
if( is_u_selected(nu1, nu1->pntsu-1) );
else {
+ /* For 2D curves blender uses orderv=0. It doesn't make any sense mathematically. */
+ /* but after rotating orderu=0 will be confusing. */
+ if (nu1->orderv == 0) nu1->orderv= 1;
+
rotate_direction_nurb(nu1);
if( is_u_selected(nu1, nu1->pntsu-1) );
else {
@@ -2818,6 +2861,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
/* 2nd nurbs: u = 0 selected */
if( is_u_selected(nu2, 0) );
else {
+ if (nu2->orderv == 0) nu2->orderv= 1;
rotate_direction_nurb(nu2);
if( is_u_selected(nu2, 0) );
else {
@@ -2863,8 +2907,8 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu
/* merge */
origu= nu1->pntsu;
nu1->pntsu+= nu2->pntsu;
- if(nu1->orderu<3) nu1->orderu++;
- if(nu1->orderv<3) nu1->orderv++;
+ if(nu1->orderu<3 && nu1->orderu<nu1->pntsu) nu1->orderu++;
+ if(nu1->orderv<3 && nu1->orderv<nu1->pntsv) nu1->orderv++;
temp= nu1->bp;
nu1->bp= MEM_mallocN(nu1->pntsu*nu1->pntsv*sizeof(BPoint), "mergeBP");
@@ -2939,7 +2983,7 @@ static int merge_nurb(bContext *C, wmOperator *op)
BLI_freelistN(&nsortbase);
return OPERATOR_CANCELLED;
}
-
+
while(nus2) {
merge_2_nurb(op, editnurb, nus1->nu, nus2->nu);
nus2= nus2->next;
@@ -2992,7 +3036,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
/* find both nurbs and points, nu1 will be put behind nu2 */
for(nu= editnurb->first; nu; nu= nu->next) {
- if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic */
+ if((nu->flagu & CU_NURB_CYCLIC)==0) { /* not cyclic */
if(nu->type == CU_BEZIER) {
bezt= nu->bezt;
if(nu1==0) {
@@ -3156,12 +3200,18 @@ int mouse_nurb(bContext *C, short mval[2], int extend)
if(bezt) {
- if(hand==1) select_beztriple(bezt, SELECT, 1, HIDDEN);
- else if(hand==0) bezt->f1|= SELECT;
- else bezt->f3|= SELECT;
+ if(hand==1) {
+ select_beztriple(bezt, SELECT, 1, HIDDEN);
+ cu->lastsel= bezt;
+ } else {
+ if(hand==0) bezt->f1|= SELECT;
+ else bezt->f3|= SELECT;
+
+ cu->lastsel= NULL;
+ }
}
else {
- cu->lastselbp= bp;
+ cu->lastsel= bp;
select_bpoint(bp, SELECT, 1, HIDDEN);
}
@@ -3169,8 +3219,13 @@ int mouse_nurb(bContext *C, short mval[2], int extend)
else {
if(bezt) {
if(hand==1) {
- if(bezt->f2 & SELECT) select_beztriple(bezt, DESELECT, 1, HIDDEN);
- else select_beztriple(bezt, SELECT, 1, HIDDEN);
+ if(bezt->f2 & SELECT) {
+ select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ if (bezt == cu->lastsel) cu->lastsel = NULL;
+ } else {
+ select_beztriple(bezt, SELECT, 1, HIDDEN);
+ cu->lastsel= bezt;
+ }
} else if(hand==0) {
bezt->f1 ^= SELECT;
} else {
@@ -3178,10 +3233,12 @@ int mouse_nurb(bContext *C, short mval[2], int extend)
}
}
else {
- if(bp->f1 & SELECT) select_bpoint(bp, DESELECT, 1, HIDDEN);
- else {
+ if(bp->f1 & SELECT) {
+ select_bpoint(bp, DESELECT, 1, HIDDEN);
+ if (cu->lastsel == bp) cu->lastsel = NULL;
+ } else {
select_bpoint(bp, SELECT, 1, HIDDEN);
- cu->lastselbp= bp;
+ cu->lastsel= bp;
}
}
@@ -3284,7 +3341,7 @@ static int spin_nurb(bContext *C, Scene *scene, Object *obedit, float *dvec, flo
for(nu= editnurb->first; nu; nu= nu->next) {
if(isNurbsel(nu)) {
nu->orderv= 4;
- nu->flagv |= CU_CYCLIC;
+ nu->flagv |= CU_NURB_CYCLIC;
makeknots(nu, 2);
}
}
@@ -3357,7 +3414,6 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
copy_m3_m4(mat, obedit->obmat);
invert_m3_m3(imat,mat);
- view3d_operator_needs_opengl(C);
findselectedNurbvert(editnurb, &nu, &bezt, &bp);
if(bezt==0 && bp==0) return OPERATOR_CANCELLED;
@@ -3396,13 +3452,13 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
nu->pntsu++;
if(mode=='e') {
- VECCOPY(newbezt->vec[0], bezt->vec[0]);
- VECCOPY(newbezt->vec[1], bezt->vec[1]);
- VECCOPY(newbezt->vec[2], bezt->vec[2]);
+ copy_v3_v3(newbezt->vec[0], bezt->vec[0]);
+ copy_v3_v3(newbezt->vec[1], bezt->vec[1]);
+ copy_v3_v3(newbezt->vec[2], bezt->vec[2]);
}
else {
- VECCOPY(newbezt->vec[1], location);
- sub_v3_v3v3(newbezt->vec[1],newbezt->vec[1], obedit->obmat[3]);
+ copy_v3_v3(newbezt->vec[1], location);
+ sub_v3_v3(newbezt->vec[1], obedit->obmat[3]);
mul_m3_v3(imat,newbezt->vec[1]);
sub_v3_v3v3(temp, newbezt->vec[1],temp);
add_v3_v3v3(newbezt->vec[0], bezt->vec[0],temp);
@@ -3444,11 +3500,11 @@ static int addvert_Nurb(bContext *C, short mode, float location[3])
makeknots(nu, 1);
if(mode=='e') {
- VECCOPY(newbp->vec, bp->vec);
+ copy_v3_v3(newbp->vec, bp->vec);
}
else {
- VECCOPY(newbp->vec, location);
- sub_v3_v3v3(newbp->vec, newbp->vec, obedit->obmat[3]);
+ copy_v3_v3(newbp->vec, location);
+ sub_v3_v3(newbp->vec, obedit->obmat[3]);
mul_m3_v3(imat,newbp->vec);
newbp->vec[3]= 1.0;
}
@@ -3477,7 +3533,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
RegionView3D *rv3d= CTX_wm_region_view3d(C);
ViewContext vc;
- float location[3];
+ float location[3] = {0.0f, 0.0f, 0.0f};
short mval[2];
if(rv3d && !RNA_property_is_set(op->ptr, "location")) {
@@ -3587,7 +3643,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
bp= nu->bp;
while(a--) {
if( bp->f1 & SELECT ) {
- nu->flagu ^= CU_CYCLIC;
+ nu->flagu ^= CU_NURB_CYCLIC;
break;
}
bp++;
@@ -3598,7 +3654,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
bezt= nu->bezt;
while(a--) {
if( BEZSELECTED_HIDDENHANDLES(cu, bezt) ) {
- nu->flagu ^= CU_CYCLIC;
+ nu->flagu ^= CU_NURB_CYCLIC;
break;
}
bezt++;
@@ -3611,7 +3667,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
bp= nu->bp;
while(a--) {
if( bp->f1 & SELECT ) {
- nu->flagu ^= CU_CYCLIC;
+ nu->flagu ^= CU_NURB_CYCLIC;
makeknots(nu, 1); /* 1==u type is ignored for cyclic curves */
break;
}
@@ -3626,11 +3682,11 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op)
if( bp->f1 & SELECT) {
if(direction==0 && nu->pntsu>1) {
- nu->flagu ^= CU_CYCLIC;
+ nu->flagu ^= CU_NURB_CYCLIC;
makeknots(nu, 1); /* 1==u type is ignored for cyclic curves */
}
if(direction==1 && nu->pntsv>1) {
- nu->flagv ^= CU_CYCLIC;
+ nu->flagv ^= CU_NURB_CYCLIC;
makeknots(nu, 2); /* 2==v type is ignored for cyclic curves */
}
break;
@@ -3699,7 +3755,7 @@ void CURVE_OT_cyclic_toggle(wmOperatorType *ot)
static int select_linked_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
- RegionView3D *rv3d= CTX_wm_region_view3d(C);
+ RegionView3D *rv3d= ED_view3d_context_rv3d(C);
ViewContext vc;
Nurb *nu;
BezTriple *bezt;
@@ -3786,7 +3842,7 @@ static int select_row_exec(bContext *C, wmOperator *op)
if(editnurb->first==0)
return OPERATOR_CANCELLED;
- if(cu->lastselbp==NULL)
+ if(cu->lastsel==NULL)
return OPERATOR_CANCELLED;
/* find the correct nurb and toggle with u of v */
@@ -3794,7 +3850,7 @@ static int select_row_exec(bContext *C, wmOperator *op)
bp= nu->bp;
for(v=0; v<nu->pntsv; v++) {
for(u=0; u<nu->pntsu; u++, bp++) {
- if(bp==cu->lastselbp) {
+ if(bp==cu->lastsel) {
if(bp->f1 & SELECT) {
ok= 1;
break;
@@ -3805,11 +3861,11 @@ static int select_row_exec(bContext *C, wmOperator *op)
}
if(ok) {
- if(last==cu->lastselbp) {
+ if(last==cu->lastsel) {
direction= 1-direction;
setflagsNurb(editnurb, 0);
}
- last= cu->lastselbp;
+ last= cu->lastsel;
bp= nu->bp;
for(a=0; a<nu->pntsv; a++) {
@@ -4215,37 +4271,128 @@ void CURVE_OT_select_random(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", FALSE, "Extend Selection", "Extend selection instead of deselecting everything first.");
}
-/********************** select every nth *********************/
+/********************* every nth number of point *******************/
+
+static int point_on_nurb(Nurb *nu, void *point)
+{
+ if (nu->bezt) {
+ BezTriple *bezt= (BezTriple*)point;
+ return bezt >= nu->bezt && bezt < nu->bezt + nu->pntsu;
+ } else {
+ BPoint *bp= (BPoint*)point;
+ return bp >= nu->bp && bp < nu->bp + nu->pntsu * nu->pntsv;
+ }
+}
-static int select_every_nth_exec(bContext *C, wmOperator *op)
+static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth)
+{
+ int a, start;
+
+ start= bezt - nu->bezt;
+ a= nu->pntsu;
+ bezt= nu->bezt + a - 1;
+
+ while (a--) {
+ if (abs(start - a) % nth) {
+ select_beztriple(bezt, DESELECT, 1, HIDDEN);
+ }
+
+ bezt--;
+ }
+}
+
+static void select_nth_bp(Nurb *nu, BPoint *bp, int nth)
+{
+ int a, startrow, startpnt;
+ int dist, 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--) {
+ dist= abs(pnt - startpnt) + abs(row - startrow);
+ if (dist % nth) {
+ select_bpoint(bp, DESELECT, 1, HIDDEN);
+ }
+
+ pnt--;
+ if (pnt < 0) {
+ pnt= nu->pntsu - 1;
+ row--;
+ }
+
+ bp--;
+ }
+}
+
+int CU_select_nth(Object *obedit, int nth)
+{
+ Curve *cu= (Curve*)obedit->data;
+ ListBase *nubase= cu->editnurb;
+ Nurb *nu;
+ int ok=0;
+
+ /* Search nurb to which selected point belongs to */
+ nu= nubase->first;
+ while (nu) {
+ if (point_on_nurb(nu, cu->lastsel)) {
+ ok= 1;
+ break;
+ }
+ nu= nu->next;
+ }
+
+ if (!ok) return 0;
+
+ if (nu->bezt) {
+ select_nth_bezt(nu, cu->lastsel, nth);
+ } else {
+ select_nth_bp(nu, cu->lastsel, nth);
+ }
+
+ return 1;
+}
+
+static int select_nth_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
- ListBase *editnurb= curve_get_editcurve(obedit);
- int n= RNA_int_get(op->ptr, "n");
-
- select_adjacent_cp(editnurb, n, 1, SELECT);
- select_adjacent_cp(editnurb, -n, 1, SELECT);
-
+ int nth= RNA_int_get(op->ptr, "nth");
+
+ if (!CU_select_nth(obedit, nth)) {
+ if (obedit->type == OB_SURF) {
+ BKE_report(op->reports, RPT_ERROR, "Surface hasn't got active point");
+ } else {
+ BKE_report(op->reports, RPT_ERROR, "Curve hasn't got active point");
+ }
+
+ return OPERATOR_CANCELLED;
+ }
+
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
-void CURVE_OT_select_every_nth(wmOperatorType *ot)
+void CURVE_OT_select_nth(wmOperatorType *ot)
{
/* identifiers */
- ot->name= "Select Every Nth";
- ot->idname= "CURVE_OT_select_every_nth";
-
+ ot->name= "Select Nth";
+ ot->description= "";
+ ot->idname= "CURVE_OT_select_nth";
+
/* api callbacks */
- ot->exec= select_every_nth_exec;
+ ot->exec= select_nth_exec;
ot->poll= ED_operator_editsurfcurve;
-
+
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
- /* properties */
- RNA_def_int(ot->srna, "n", 2, 2, INT_MAX, "N", "Select every Nth element", 2, 25);
+ RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
}
/********************** add duplicate operator *********************/
@@ -4255,6 +4402,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
adduplicateflagNurb(obedit, 1);
+ WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
return OPERATOR_FINISHED;
}
@@ -4429,10 +4577,10 @@ static int delete_exec(bContext *C, wmOperator *op)
bezt2= bezt+1;
if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) ;
else { /* maybe do not make cyclic */
- if(a==0 && (nu->flagu & CU_CYCLIC) ) {
+ if(a==0 && (nu->flagu & CU_NURB_CYCLIC) ) {
bezt2= bezt+(nu->pntsu-1);
if( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) {
- nu->flagu &= ~CU_CYCLIC;
+ nu->flagu &= ~CU_NURB_CYCLIC;
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
}
@@ -4455,10 +4603,10 @@ static int delete_exec(bContext *C, wmOperator *op)
bp2= bp+1;
if( bp2->f1 & 1 ) ;
else { /* maybe do not make cyclic */
- if(a==0 && (nu->flagu & CU_CYCLIC) ) {
+ if(a==0 && (nu->flagu & CU_NURB_CYCLIC) ) {
bp2= bp+(nu->pntsu-1);
if( bp2->f1 & SELECT ) {
- nu->flagu &= ~CU_CYCLIC;
+ nu->flagu &= ~CU_NURB_CYCLIC;
WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
}
@@ -4483,14 +4631,14 @@ static int delete_exec(bContext *C, wmOperator *op)
BLI_remlink(editnurb, nu);
freeNurb(nu); nu = NULL;
}
- else if(nu1->flagu & CU_CYCLIC) { /* cyclic */
+ else if(nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */
bezt =
(BezTriple*)MEM_mallocN((cut+1) * sizeof(BezTriple), "delNurb1");
memcpy(bezt, nu1->bezt,(cut+1)*sizeof(BezTriple));
a= nu1->pntsu-cut-1;
memcpy(nu1->bezt, bezt2, a*sizeof(BezTriple));
memcpy(nu1->bezt+a, bezt, (cut+1)*sizeof(BezTriple));
- nu1->flagu &= ~CU_CYCLIC;
+ nu1->flagu &= ~CU_NURB_CYCLIC;
MEM_freeN(bezt);
calchandlesNurb(nu);
}
@@ -4525,14 +4673,14 @@ static int delete_exec(bContext *C, wmOperator *op)
BLI_remlink(editnurb, nu);
freeNurb(nu); nu= NULL;
}
- else if(nu1->flagu & CU_CYCLIC) { /* cyclic */
+ else if(nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */
bp =
(BPoint*)MEM_mallocN((cut+1) * sizeof(BPoint), "delNurb5");
memcpy(bp, nu1->bp,(cut+1)*sizeof(BPoint));
a= nu1->pntsu-cut-1;
memcpy(nu1->bp, bp2, a*sizeof(BPoint));
memcpy(nu1->bp+a, bp, (cut+1)*sizeof(BPoint));
- nu1->flagu &= ~CU_CYCLIC;
+ nu1->flagu &= ~CU_NURB_CYCLIC;
MEM_freeN(bp);
}
else { /* add new curve */
@@ -4572,8 +4720,8 @@ static int delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
if(obedit->type==OB_SURF) {
pup= uiPupMenuBegin(C, "Delete", 0);
layout= uiPupMenuLayout(pup);
- uiItemEnumO(layout, NULL, 0, op->type->idname, "type", 0);
- uiItemEnumO(layout, NULL, 0, op->type->idname, "type", 2);
+ uiItemEnumO(layout, op->type->idname, NULL, 0, "type", 0);
+ uiItemEnumO(layout, op->type->idname, NULL, 0, "type", 2);
uiPupMenuEnd(C, pup);
}
else {
@@ -4737,7 +4885,6 @@ int join_curve_exec(bContext *C, wmOperator *op)
}
/************ add primitive, used by object/ module ****************/
-
Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
{
static int xzproj= 0; /* this function calls itself... */
@@ -4848,7 +4995,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
nu->pntsu= 5;
nu->pntsv= 1;
nu->orderu= 5;
- nu->flagu= 2; /* endpoint */
+ nu->flagu= CU_NURB_ENDPOINT; /* endpoint */
nu->resolu= 8;
nu->bp= callocstructN(BPoint, 5, "addNurbprim3");
@@ -4887,7 +5034,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
if (!force_3d) nu->flag |= CU_2D;
nu->pntsu= 4;
nu->bezt= callocstructN(BezTriple, 4, "addNurbprim1");
- nu->flagu= CU_CYCLIC;
+ nu->flagu= CU_NURB_CYCLIC;
bezt= nu->bezt;
bezt->h1= bezt->h2= HD_AUTO;
@@ -4924,7 +5071,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
nu->pntsv= 1;
nu->orderu= 4;
nu->bp= callocstructN(BPoint, 8, "addNurbprim6");
- nu->flagu= CU_CYCLIC;
+ nu->flagu= CU_NURB_CYCLIC;
bp= nu->bp;
for(a=0; a<8; a++) {
@@ -5046,7 +5193,7 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
mul_m4_v3(mat,bp->vec);
bp++;
}
- nu->flagu= 4;
+ nu->flagu= CU_NURB_BEZIER;
makeknots(nu, 1);
BLI_addtail(editnurb, nu); /* temporal for spin */
@@ -5072,8 +5219,8 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
float tmp_vec[3] = {0.f, 0.f, 0.f};
if(newname) {
- rename_id((ID *)obedit, "SurfDonut");
- rename_id((ID *)obedit->data, "SurfDonut");
+ rename_id((ID *)obedit, "SurfTorus");
+ rename_id((ID *)obedit->data, "SurfTorus");
}
xzproj= 1;
@@ -5109,6 +5256,318 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newname)
return nu;
}
+static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) {
+
+ Object *obedit= CTX_data_edit_object(C);
+ ListBase *editnurb;
+ Nurb *nu;
+ int newob= 0;
+ int enter_editmode;
+ unsigned int layer;
+ float loc[3], rot[3];
+ float mat[4][4];
+
+ if(!ED_object_add_generic_get_opts(C, op, loc, rot, &enter_editmode, &layer))
+ return OPERATOR_CANCELLED;
+
+ if (!isSurf) { /* adding curve */
+ if(obedit==NULL || obedit->type!=OB_CURVE) {
+ Curve *cu;
+ obedit= ED_object_add_type(C, OB_CURVE, loc, rot, TRUE, layer);
+ newob = 1;
+
+ cu= (Curve*)obedit->data;
+ cu->flag |= CU_DEFORM_FILL;
+ if(type & CU_PRIM_PATH)
+ cu->flag |= CU_PATH|CU_3D;
+ } else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
+ } else { /* adding surface */
+ if(obedit==NULL || obedit->type!=OB_SURF) {
+ obedit= ED_object_add_type(C, OB_SURF, loc, rot, TRUE, layer);
+ newob = 1;
+ } else DAG_id_flush_update(&obedit->id, OB_RECALC_DATA);
+ }
+
+ ED_object_new_primitive_matrix(C, obedit, loc, rot, mat);
+
+ nu= add_nurbs_primitive(C, mat, type, newob);
+ editnurb= curve_get_editcurve(obedit);
+ BLI_addtail(editnurb, nu);
+
+ /* userdef */
+ if (newob && !enter_editmode) {
+ ED_object_exit_editmode(C, EM_FREEDATA);
+ }
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, obedit);
+
+ return OPERATOR_FINISHED;
+}
+
+static int curve_prim_add(bContext *C, wmOperator *op, int type) {
+ return curvesurf_prim_add(C, op, type, 0);
+}
+
+static int surf_prim_add(bContext *C, wmOperator *op, int type) {
+ return curvesurf_prim_add(C, op, type, 1);
+}
+
+/* ******************** Curves ******************* */
+
+static int add_primitive_bezier_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_BEZIER|CU_PRIM_CURVE);
+}
+
+void CURVE_OT_primitive_bezier_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Bezier";
+ ot->description= "Construct a Bezier Curve";
+ ot->idname= "CURVE_OT_primitive_bezier_curve_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_bezier_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_bezier_circle_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_BEZIER|CU_PRIM_CIRCLE);
+}
+
+void CURVE_OT_primitive_bezier_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Circle";
+ ot->description= "Construct a Bezier Circle";
+ ot->idname= "CURVE_OT_primitive_bezier_circle_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_bezier_circle_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_curve_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_NURBS|CU_PRIM_CURVE);
+}
+
+void CURVE_OT_primitive_nurbs_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Nurbs Curve";
+ ot->description= "Construct a Nurbs Curve";
+ ot->idname= "CURVE_OT_primitive_nurbs_curve_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_curve_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_circle_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_NURBS|CU_PRIM_CIRCLE);
+}
+
+void CURVE_OT_primitive_nurbs_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Nurbs Circle";
+ ot->description= "Construct a Nurbs Circle";
+ ot->idname= "CURVE_OT_primitive_nurbs_circle_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_circle_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_curve_path_exec(bContext *C, wmOperator *op)
+{
+ return curve_prim_add(C, op, CU_NURBS|CU_PRIM_PATH);
+}
+
+void CURVE_OT_primitive_nurbs_path_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Path";
+ ot->description= "Construct a Path";
+ ot->idname= "CURVE_OT_primitive_nurbs_path_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_curve_path_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+/* **************** NURBS surfaces ********************** */
+static int add_primitive_nurbs_surface_curve_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_CURVE|CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_curve_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Curve";
+ ot->description= "Construct a Nurbs surface Curve";
+ ot->idname= "SURFACE_OT_primitive_nurbs_surface_curve_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_surface_curve_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_surface_circle_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_CIRCLE|CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_circle_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Circle";
+ ot->description= "Construct a Nurbs surface Circle";
+ ot->idname= "SURFACE_OT_primitive_nurbs_surface_circle_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_surface_circle_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_surface_surface_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_PATCH|CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_surface_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Patch";
+ ot->description= "Construct a Nurbs surface Patch";
+ ot->idname= "SURFACE_OT_primitive_nurbs_surface_surface_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_surface_surface_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_surface_tube_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_TUBE|CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_tube_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Tube";
+ ot->description= "Construct a Nurbs surface Tube";
+ ot->idname= "SURFACE_OT_primitive_nurbs_surface_tube_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_surface_tube_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_surface_sphere_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_SPHERE|CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_sphere_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Sphere";
+ ot->description= "Construct a Nurbs surface Sphere";
+ ot->idname= "SURFACE_OT_primitive_nurbs_surface_sphere_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_surface_sphere_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
+static int add_primitive_nurbs_surface_donut_exec(bContext *C, wmOperator *op)
+{
+ return surf_prim_add(C, op, CU_PRIM_DONUT|CU_NURBS);
+}
+
+void SURFACE_OT_primitive_nurbs_surface_donut_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Surface Donut";
+ ot->description= "Construct a Nurbs surface Donut";
+ ot->idname= "SURFACE_OT_primitive_nurbs_surface_donut_add";
+
+ /* api callbacks */
+ ot->invoke= ED_object_add_generic_invoke;
+ ot->exec= add_primitive_nurbs_surface_donut_exec;
+ ot->poll= ED_operator_scene_editable;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ ED_object_add_generic_props(ot, TRUE);
+}
+
/***************** clear tilt operator ********************/
static int clear_tilt_exec(bContext *C, wmOperator *op)
@@ -5162,49 +5621,87 @@ void CURVE_OT_tilt_clear(wmOperatorType *ot)
/****************** undo for curves ****************/
-static void undoCurve_to_editCurve(void *lbu, void *lbe, void *obdata)
+static void *undo_check_lastsel(void *lastsel, Nurb *nu, Nurb *newnu)
{
- ListBase *lb= lbu;
- ListBase *editnurb= lbe;
+ if (nu->bezt) {
+ BezTriple *lastbezt= (BezTriple*)lastsel;
+ if (lastbezt >= nu->bezt && lastbezt < nu->bezt + nu->pntsu) {
+ return newnu->bezt + (lastbezt - nu->bezt);
+ }
+ } else {
+ BPoint *lastbp= (BPoint*)lastsel;
+ if (lastbp >= nu->bp && lastbp < nu->bp + nu->pntsu*nu->pntsv) {
+ return newnu->bp + (lastbp - nu->bp);
+ }
+ }
+
+ return NULL;
+}
+
+static void undoCurve_to_editCurve(void *ucu, void *cue)
+{
+ Curve *cu= cue;
+ UndoCurve *undoCurve= ucu;
+ ListBase *undobase= &undoCurve->nubase;
+ ListBase *editbase= cu->editnurb;
Nurb *nu, *newnu;
-
- freeNurblist(editnurb);
+ void *lastsel= NULL;
+
+ freeNurblist(editbase);
/* copy */
- for(nu= lb->first; nu; nu= nu->next) {
+ for(nu= undobase->first; nu; nu= nu->next) {
newnu= duplicateNurb(nu);
- BLI_addtail(editnurb, newnu);
+
+ if (lastsel == NULL) {
+ lastsel= undo_check_lastsel(undoCurve->lastsel, nu, newnu);
+ }
+
+ BLI_addtail(editbase, newnu);
}
+
+ cu->lastsel= lastsel;
}
-static void *editCurve_to_undoCurve(void *lbe, void *obdata)
+static void *editCurve_to_undoCurve(void *lbe, void *cue)
{
- ListBase *editnurb= lbe;
- ListBase *lb;
+ Curve *cu= cue;
+ ListBase *nubase= cu->editnurb;
+ UndoCurve *undoCurve;
Nurb *nu, *newnu;
+ void *lastsel= NULL;
+
+ undoCurve= MEM_callocN(sizeof(UndoCurve), "undoCurve");
- lb= MEM_callocN(sizeof(ListBase), "listbase undo");
-
/* copy */
- for(nu= editnurb->first; nu; nu= nu->next) {
+ for(nu= nubase->first; nu; nu= nu->next) {
newnu= duplicateNurb(nu);
- BLI_addtail(lb, newnu);
+
+ if (lastsel == NULL) {
+ lastsel= undo_check_lastsel(cu->lastsel, nu, newnu);
+ }
+
+ BLI_addtail(&undoCurve->nubase, newnu);
}
- return lb;
+
+ undoCurve->lastsel= lastsel;
+
+ return undoCurve;
}
-static void free_undoCurve(void *lbv)
+static void free_undoCurve(void *ucv)
{
- ListBase *lb= lbv;
-
- freeNurblist(lb);
- MEM_freeN(lb);
+ UndoCurve *undoCurve= ucv;
+
+ freeNurblist(&undoCurve->nubase);
+
+ MEM_freeN(undoCurve);
}
static void *get_data(bContext *C)
{
Object *obedit= CTX_data_edit_object(C);
- return curve_get_editcurve(obedit);
+ return obedit->data;
}
/* and this is all the undo system needs to know */