BLI_bitmap: rename macros
[blender.git] / source / blender / editors / curve / editcurve.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/curve/editcurve.c
29  *  \ingroup edcurve
30  */
31
32 #include "DNA_key_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35 #include "DNA_anim_types.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_bitmap.h"
41 #include "BLI_math.h"
42 #include "BLI_rand.h"
43 #include "BLI_ghash.h"
44
45 #include "BLF_translation.h"
46
47 #include "BKE_context.h"
48 #include "BKE_curve.h"
49 #include "BKE_depsgraph.h"
50 #include "BKE_displist.h"
51 #include "BKE_fcurve.h"
52 #include "BKE_global.h"
53 #include "BKE_key.h"
54 #include "BKE_main.h"
55 #include "BKE_report.h"
56 #include "BKE_animsys.h"
57 #include "BKE_action.h"
58 #include "BKE_modifier.h"
59
60 #include "WM_api.h"
61 #include "WM_types.h"
62
63 #include "ED_keyframes_edit.h"
64 #include "ED_object.h"
65 #include "ED_screen.h"
66 #include "ED_transform.h"
67 #include "ED_types.h"
68 #include "ED_util.h"
69 #include "ED_view3d.h"
70 #include "ED_curve.h"
71
72 #include "curve_intern.h"
73
74 #include "UI_interface.h"
75 #include "UI_resources.h"
76
77 #include "RNA_access.h"
78 #include "RNA_define.h"
79 #include "RNA_enum_types.h"
80
81 /* Undo stuff */
82 typedef struct {
83         ListBase nubase;
84         int actvert;
85         GHash *undoIndex;
86         ListBase fcurves, drivers;
87         int actnu;
88 } UndoCurve;
89
90 /* Definitions needed for shape keys */
91 typedef struct {
92         void *orig_cv;
93         int key_index, nu_index, pt_index, vertex_index;
94         bool switched;
95         Nurb *orig_nu;
96 } CVKeyIndex;
97
98 typedef enum eVisible_Types {
99         HIDDEN = true,
100         VISIBLE = false,
101 } eVisible_Types;
102
103 typedef enum eEndPoint_Types {
104         FIRST = true,
105         LAST = false,
106 } eEndPoint_Types;
107
108 typedef enum eCurveElem_Types {
109         CURVE_VERTEX = 0,
110         CURVE_SEGMENT,
111 } eCurveElem_Types;
112
113 void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
114 static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus);
115 static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
116 static int curve_delete_segments(Object *obedit, const bool split);
117
118 ListBase *object_editcurve_get(Object *ob)
119 {
120         if (ob && ELEM(ob->type, OB_CURVE, OB_SURF)) {
121                 Curve *cu = ob->data;
122                 return &cu->editnurb->nurbs;
123         }
124         return NULL;
125 }
126
127 /* ******************* SELECTION FUNCTIONS ********************* */
128
129
130 /* returns 1 in case (de)selection was successful */
131 static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden)
132 {       
133         if ((bezt->hide == 0) || (hidden == HIDDEN)) {
134                 if (selstatus == SELECT) { /* selects */
135                         bezt->f1 |= flag;
136                         bezt->f2 |= flag;
137                         bezt->f3 |= flag;
138                         return true;
139                 }
140                 else { /* deselects */
141                         bezt->f1 &= ~flag;
142                         bezt->f2 &= ~flag;
143                         bezt->f3 &= ~flag;
144                         return true;
145                 }
146         }
147         
148         return false;
149 }
150
151 /* returns 1 in case (de)selection was successful */
152 static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden)
153 {       
154         if ((bp->hide == 0) || (hidden == 1)) {
155                 if (selstatus == SELECT) {
156                         bp->f1 |= flag;
157                         return true;
158                 }
159                 else {
160                         bp->f1 &= ~flag;
161                         return true;
162                 }
163         }
164
165         return false;
166 }
167
168 static bool swap_selection_beztriple(BezTriple *bezt)
169 {
170         if (bezt->f2 & SELECT)
171                 return select_beztriple(bezt, DESELECT, SELECT, VISIBLE);
172         else
173                 return select_beztriple(bezt, SELECT, SELECT, VISIBLE);
174 }
175
176 static bool swap_selection_bpoint(BPoint *bp)
177 {
178         if (bp->f1 & SELECT)
179                 return select_bpoint(bp, DESELECT, SELECT, VISIBLE);
180         else
181                 return select_bpoint(bp, SELECT, SELECT, VISIBLE);
182 }
183
184 int isNurbsel(Nurb *nu)
185 {
186         BezTriple *bezt;
187         BPoint *bp;
188         int a;
189
190         if (nu->type == CU_BEZIER) {
191                 bezt = nu->bezt;
192                 a = nu->pntsu;
193                 while (a--) {
194                         if ( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) return 1;
195                         bezt++;
196                 }
197         }
198         else {
199                 bp = nu->bp;
200                 a = nu->pntsu * nu->pntsv;
201                 while (a--) {
202                         if (bp->f1 & SELECT) return 1;
203                         bp++;
204                 }
205         }
206         return 0;
207 }
208
209 static int isNurbsel_count(Curve *cu, Nurb *nu)
210 {
211         BezTriple *bezt;
212         BPoint *bp;
213         int a, sel = 0;
214
215         if (nu->type == CU_BEZIER) {
216                 bezt = nu->bezt;
217                 a = nu->pntsu;
218                 while (a--) {
219                         if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) sel++;
220                         bezt++;
221                 }
222         }
223         else {
224                 bp = nu->bp;
225                 a = nu->pntsu * nu->pntsv;
226                 while (a--) {
227                         if ( (bp->f1 & SELECT) ) sel++;
228                         bp++;
229                 }
230         }
231         return sel;
232 }
233
234 /* ******************* PRINTS ********************* */
235
236 void printknots(Object *obedit)
237 {
238         ListBase *editnurb = object_editcurve_get(obedit);
239         Nurb *nu;
240         int a, num;
241
242         for (nu = editnurb->first; nu; nu = nu->next) {
243                 if (isNurbsel(nu) && nu->type == CU_NURBS) {
244                         if (nu->knotsu) {
245                                 num = KNOTSU(nu);
246                                 for (a = 0; a < num; a++) printf("knotu %d: %f\n", a, nu->knotsu[a]);
247                         }
248                         if (nu->knotsv) {
249                                 num = KNOTSV(nu);
250                                 for (a = 0; a < num; a++) printf("knotv %d: %f\n", a, nu->knotsv[a]);
251                         }
252                 }
253         }
254 }
255
256 /* ********************* Shape keys *************** */
257
258 static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index, Nurb *orig_nu)
259 {
260         CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), "init_cvKeyIndex");
261
262         cvIndex->orig_cv = cv;
263         cvIndex->key_index = key_index;
264         cvIndex->nu_index = nu_index;
265         cvIndex->pt_index = pt_index;
266         cvIndex->vertex_index = vertex_index;
267         cvIndex->switched = false;
268         cvIndex->orig_nu = orig_nu;
269
270         return cvIndex;
271 }
272
273 static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
274 {
275         Nurb *nu = editnurb->nurbs.first;
276         Nurb *orignu = origBase->first;
277         GHash *gh;
278         BezTriple *bezt, *origbezt;
279         BPoint *bp, *origbp;
280         CVKeyIndex *keyIndex;
281         int a, key_index = 0, nu_index = 0, pt_index = 0, vertex_index = 0;
282
283         if (editnurb->keyindex) return;
284
285         gh = BLI_ghash_ptr_new("editNurb keyIndex");
286
287         while (orignu) {
288                 if (orignu->bezt) {
289                         a = orignu->pntsu;
290                         bezt = nu->bezt;
291                         origbezt = orignu->bezt;
292                         pt_index = 0;
293                         while (a--) {
294                                 keyIndex = init_cvKeyIndex(origbezt, key_index, nu_index, pt_index, vertex_index, orignu);
295                                 BLI_ghash_insert(gh, bezt, keyIndex);
296                                 key_index += 12;
297                                 vertex_index += 3;
298                                 bezt++;
299                                 origbezt++;
300                                 pt_index++;
301                         }
302                 }
303                 else {
304                         a = orignu->pntsu * orignu->pntsv;
305                         bp = nu->bp;
306                         origbp = orignu->bp;
307                         pt_index = 0;
308                         while (a--) {
309                                 keyIndex = init_cvKeyIndex(origbp, key_index, nu_index, pt_index, vertex_index, orignu);
310                                 BLI_ghash_insert(gh, bp, keyIndex);
311                                 key_index += 4;
312                                 bp++;
313                                 origbp++;
314                                 pt_index++;
315                                 vertex_index++;
316                         }
317                 }
318
319                 nu = nu->next;
320                 orignu = orignu->next;
321                 nu_index++;
322         }
323
324         editnurb->keyindex = gh;
325 }
326
327 static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv)
328 {
329         return BLI_ghash_lookup(editnurb->keyindex, cv);
330 }
331
332 static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, void *cv)
333 {
334         return BLI_ghash_popkey(editnurb->keyindex, cv, NULL);
335 }
336
337 static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt)
338 {
339         CVKeyIndex *index = getCVKeyIndex(editnurb, bezt);
340
341         if (!index) {
342                 return NULL;
343         }
344
345         return (BezTriple *)index->orig_cv;
346 }
347
348 static BPoint *getKeyIndexOrig_bp(EditNurb *editnurb, BPoint *bp)
349 {
350         CVKeyIndex *index = getCVKeyIndex(editnurb, bp);
351
352         if (!index) {
353                 return NULL;
354         }
355
356         return (BPoint *)index->orig_cv;
357 }
358
359 static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv)
360 {
361         CVKeyIndex *index = getCVKeyIndex(editnurb, cv);
362
363         if (!index) {
364                 return -1;
365         }
366
367         return index->key_index;
368 }
369
370 static void keyIndex_delCV(EditNurb *editnurb, void *cv)
371 {
372         if (!editnurb->keyindex) {
373                 return;
374         }
375
376         BLI_ghash_remove(editnurb->keyindex, cv, NULL, MEM_freeN);
377 }
378
379 static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
380 {
381         keyIndex_delCV(editnurb, bezt);
382 }
383
384 static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp)
385 {
386         keyIndex_delCV(editnurb, bp);
387 }
388
389 static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
390 {
391         int a;
392
393         if (!editnurb->keyindex) {
394                 return;
395         }
396
397         if (nu->bezt) {
398                 BezTriple *bezt = nu->bezt;
399                 a = nu->pntsu;
400
401                 while (a--) {
402                         BLI_ghash_remove(editnurb->keyindex, bezt, NULL, MEM_freeN);
403                         bezt++;
404                 }
405         }
406         else {
407                 BPoint *bp = nu->bp;
408                 a = nu->pntsu * nu->pntsv;
409
410                 while (a--) {
411                         BLI_ghash_remove(editnurb->keyindex, bp, NULL, MEM_freeN);
412                         bp++;
413                 }
414         }
415 }
416
417 static void keyIndex_delNurbList(EditNurb *editnurb, ListBase *nubase)
418 {
419         Nurb *nu = nubase->first;
420
421         while (nu) {
422                 keyIndex_delNurb(editnurb, nu);
423
424                 nu = nu->next;
425         }
426 }
427
428 static void keyIndex_updateCV(EditNurb *editnurb, char *cv,
429                               char *newcv, int count, int size)
430 {
431         int i;
432         CVKeyIndex *index;
433
434         if (editnurb->keyindex == NULL) {
435                 /* No shape keys - updating not needed */
436                 return;
437         }
438
439         for (i = 0; i < count; i++) {
440                 index = popCVKeyIndex(editnurb, cv);
441
442                 if (index) {
443                         BLI_ghash_insert(editnurb->keyindex, newcv, index);
444                 }
445
446                 newcv += size;
447                 cv += size;
448         }
449 }
450
451 static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt,
452                                 BezTriple *newbezt, int count)
453 {
454         keyIndex_updateCV(editnurb, (char *)bezt, (char *)newbezt, count, sizeof(BezTriple));
455 }
456
457 static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp,
458                               BPoint *newbp, int count)
459 {
460         keyIndex_updateCV(editnurb, (char *)bp, (char *)newbp, count, sizeof(BPoint));
461 }
462
463 static void keyIndex_updateNurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu)
464 {
465         if (nu->bezt) {
466                 keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu);
467         }
468         else {
469                 keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv);
470         }
471 }
472
473 static void keyIndex_swap(EditNurb *editnurb, void *a, void *b)
474 {
475         CVKeyIndex *index1 = popCVKeyIndex(editnurb, a);
476         CVKeyIndex *index2 = popCVKeyIndex(editnurb, b);
477
478         if (index2) BLI_ghash_insert(editnurb->keyindex, a, index2);
479         if (index1) BLI_ghash_insert(editnurb->keyindex, b, index1);
480 }
481
482 static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu)
483 {
484         int a;
485         CVKeyIndex *index1, *index2;
486
487         if (nu->bezt) {
488                 BezTriple *bezt1, *bezt2;
489
490                 a = nu->pntsu;
491
492                 bezt1 = nu->bezt;
493                 bezt2 = bezt1 + (a - 1);
494
495                 if (a & 1) ++a;
496
497                 a /= 2;
498
499                 while (a--) {
500                         index1 = getCVKeyIndex(editnurb, bezt1);
501                         index2 = getCVKeyIndex(editnurb, bezt2);
502
503                         if (index1) index1->switched = !index1->switched;
504
505                         if (bezt1 != bezt2) {
506                                 keyIndex_swap(editnurb, bezt1, bezt2);
507
508                                 if (index2) index2->switched = !index2->switched;
509                         }
510
511                         bezt1++;
512                         bezt2--;
513                 }
514         }
515         else {
516                 BPoint *bp1, *bp2;
517
518                 if (nu->pntsv == 1) {
519                         a = nu->pntsu;
520                         bp1 = nu->bp;
521                         bp2 = bp1 + (a - 1);
522                         a /= 2;
523                         while (bp1 != bp2 && a > 0) {
524                                 index1 = getCVKeyIndex(editnurb, bp1);
525                                 index2 = getCVKeyIndex(editnurb, bp2);
526
527                                 if (index1) index1->switched = !index1->switched;
528
529                                 if (bp1 != bp2) {
530                                         if (index2) index2->switched = !index2->switched;
531
532                                         keyIndex_swap(editnurb, bp1, bp2);
533                                 }
534
535                                 a--;
536                                 bp1++;
537                                 bp2--;
538                         }
539                 }
540                 else {
541                         int b;
542
543                         for (b = 0; b < nu->pntsv; b++) {
544
545                                 bp1 = &nu->bp[b * nu->pntsu];
546                                 a = nu->pntsu;
547                                 bp2 = bp1 + (a - 1);
548                                 a /= 2;
549
550                                 while (bp1 != bp2 && a > 0) {
551                                         index1 = getCVKeyIndex(editnurb, bp1);
552                                         index2 = getCVKeyIndex(editnurb, bp2);
553
554                                         if (index1) index1->switched = !index1->switched;
555
556                                         if (bp1 != bp2) {
557                                                 if (index2) index2->switched = !index2->switched;
558
559                                                 keyIndex_swap(editnurb, bp1, bp2);
560                                         }
561
562                                         a--;
563                                         bp1++;
564                                         bp2--;
565                                 }
566                         }
567
568                 }
569         }
570 }
571
572 static void switch_keys_direction(Curve *cu, Nurb *actnu)
573 {
574         KeyBlock *currkey;
575         EditNurb *editnurb = cu->editnurb;
576         ListBase *nubase = &editnurb->nurbs;
577         Nurb *nu;
578         float *fp;
579         int a;
580
581         currkey = cu->key->block.first;
582         while (currkey) {
583                 fp = currkey->data;
584
585                 nu = nubase->first;
586                 while (nu) {
587                         if (nu->bezt) {
588                                 BezTriple *bezt = nu->bezt;
589                                 a = nu->pntsu;
590                                 if (nu == actnu) {
591                                         while (a--) {
592                                                 if (getKeyIndexOrig_bezt(editnurb, bezt)) {
593                                                         swap_v3_v3(fp, fp + 6);
594                                                         *(fp + 9) = -*(fp + 9);
595                                                         fp += 12;
596                                                 }
597                                                 bezt++;
598                                         }
599                                 }
600                                 else {
601                                         fp += a * 12;
602                                 }
603                         }
604                         else {
605                                 BPoint *bp = nu->bp;
606                                 a = nu->pntsu * nu->pntsv;
607                                 if (nu == actnu) {
608                                         while (a--) {
609                                                 if (getKeyIndexOrig_bp(editnurb, bp)) {
610                                                         *(fp + 3) = -*(fp + 3);
611                                                         fp += 4;
612                                                 }
613                                                 bp++;
614                                         }
615                                 }
616                                 else {
617                                         fp += a * 4;
618                                 }
619                         }
620
621                         nu = nu->next;
622                 }
623
624                 currkey = currkey->next;
625         }
626 }
627
628 static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu)
629 {
630         EditNurb *editnurb = cu->editnurb;
631
632         if (!editnurb->keyindex) {
633                 /* no shape keys - nothing to do */
634                 return;
635         }
636
637         keyIndex_switchDirection(editnurb, nu);
638         if (cu->key)
639                 switch_keys_direction(cu, nu);
640 }
641
642 static GHash *dupli_keyIndexHash(GHash *keyindex)
643 {
644         GHash *gh;
645         GHashIterator *hashIter;
646
647         gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex));
648
649         for (hashIter = BLI_ghashIterator_new(keyindex);
650              BLI_ghashIterator_done(hashIter) == false;
651              BLI_ghashIterator_step(hashIter))
652         {
653                 void *cv = BLI_ghashIterator_getKey(hashIter);
654                 CVKeyIndex *index = BLI_ghashIterator_getValue(hashIter);
655                 CVKeyIndex *newIndex = MEM_callocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
656
657                 memcpy(newIndex, index, sizeof(CVKeyIndex));
658
659                 BLI_ghash_insert(gh, cv, newIndex);
660         }
661
662         BLI_ghashIterator_free(hashIter);
663
664         return gh;
665 }
666
667 static void key_to_bezt(float *key, BezTriple *basebezt, BezTriple *bezt)
668 {
669         memcpy(bezt, basebezt, sizeof(BezTriple));
670         memcpy(bezt->vec, key, sizeof(float) * 9);
671         bezt->alfa = key[9];
672 }
673
674 static void bezt_to_key(BezTriple *bezt, float *key)
675 {
676         memcpy(key, bezt->vec, sizeof(float) * 9);
677         key[9] = bezt->alfa;
678 }
679
680 static void calc_keyHandles(ListBase *nurb, float *key)
681 {
682         Nurb *nu;
683         int a;
684         float *fp = key;
685         BezTriple *bezt;
686
687         nu = nurb->first;
688         while (nu) {
689                 if (nu->bezt) {
690                         BezTriple *prevp, *nextp;
691                         BezTriple cur, prev, next;
692                         float *startfp, *prevfp, *nextfp;
693
694                         bezt = nu->bezt;
695                         a = nu->pntsu;
696                         startfp = fp;
697
698                         if (nu->flagu & CU_NURB_CYCLIC) {
699                                 prevp = bezt + (a - 1);
700                                 prevfp = fp + (12 * (a - 1));
701                         }
702                         else {
703                                 prevp = NULL;
704                                 prevfp = NULL;
705                         }
706
707                         nextp = bezt + 1;
708                         nextfp = fp + 12;
709
710                         while (a--) {
711                                 key_to_bezt(fp, bezt, &cur);
712
713                                 if (nextp) key_to_bezt(nextfp, nextp, &next);
714                                 if (prevp) key_to_bezt(prevfp, prevp, &prev);
715
716                                 BKE_nurb_handle_calc(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0);
717                                 bezt_to_key(&cur, fp);
718
719                                 prevp = bezt;
720                                 prevfp = fp;
721                                 if (a == 1) {
722                                         if (nu->flagu & CU_NURB_CYCLIC) {
723                                                 nextp = nu->bezt;
724                                                 nextfp = startfp;
725                                         }
726                                         else {
727                                                 nextp = NULL;
728                                                 nextfp = NULL;
729                                         }
730                                 }
731                                 else {
732                                         nextp++;
733                                         nextfp += 12;
734                                 }
735
736                                 bezt++;
737                                 fp += 12;
738                         }
739                 }
740                 else {
741                         a = nu->pntsu * nu->pntsv;
742                         fp += a * 4;
743                 }
744
745                 nu = nu->next;
746         }
747 }
748
749 static void calc_shapeKeys(Object *obedit)
750 {
751         Curve *cu = (Curve *)obedit->data;
752
753         /* are there keys? */
754         if (cu->key) {
755                 int a, i;
756                 EditNurb *editnurb = cu->editnurb;
757                 KeyBlock *currkey;
758                 KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
759                 BezTriple *bezt, *oldbezt;
760                 BPoint *bp, *oldbp;
761                 Nurb *nu;
762                 int totvert = BKE_nurbList_verts_count(&editnurb->nurbs);
763
764                 float (*ofs)[3] = NULL;
765                 float *oldkey, *newkey, *ofp;
766
767                 /* editing the base key should update others */
768                 if (cu->key->type == KEY_RELATIVE) {
769                         int act_is_basis = 0;
770                         /* find if this key is a basis for any others */
771                         for (currkey = cu->key->block.first; currkey; currkey = currkey->next) {
772                                 if (editnurb->shapenr - 1 == currkey->relative) {
773                                         act_is_basis = 1;
774                                         break;
775                                 }
776                         }
777
778                         if (act_is_basis) { /* active key is a base */
779                                 int totvec = 0;
780
781                                 /* Calculate needed memory to store offset */
782                                 nu = editnurb->nurbs.first;
783                                 while (nu) {
784                                         if (nu->bezt) {
785                                                 /* Three vects to store handles and one for alfa */
786                                                 totvec += nu->pntsu * 4;
787                                         }
788                                         else {
789                                                 totvec += 2 * nu->pntsu * nu->pntsv;
790                                         }
791
792                                         nu = nu->next;
793                                 }
794
795                                 ofs = MEM_callocN(sizeof(float) * 3 * totvec,  "currkey->data");
796                                 nu = editnurb->nurbs.first;
797                                 i = 0;
798                                 while (nu) {
799                                         if (nu->bezt) {
800                                                 bezt = nu->bezt;
801                                                 a = nu->pntsu;
802                                                 while (a--) {
803                                                         oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
804
805                                                         if (oldbezt) {
806                                                                 int j;
807                                                                 for (j = 0; j < 3; ++j) {
808                                                                         sub_v3_v3v3(ofs[i], bezt->vec[j], oldbezt->vec[j]);
809                                                                         i++;
810                                                                 }
811                                                                 ofs[i++][0] = bezt->alfa - oldbezt->alfa;
812                                                         }
813                                                         else {
814                                                                 i += 4;
815                                                         }
816                                                         bezt++;
817                                                 }
818                                         }
819                                         else {
820                                                 bp = nu->bp;
821                                                 a = nu->pntsu * nu->pntsv;
822                                                 while (a--) {
823                                                         oldbp = getKeyIndexOrig_bp(editnurb, bp);
824                                                         if (oldbp) {
825                                                                 sub_v3_v3v3(ofs[i], bp->vec, oldbp->vec);
826                                                                 ofs[i + 1][0] = bp->alfa - oldbp->alfa;
827                                                         }
828                                                         i += 2;
829                                                         bp++;
830                                                 }
831                                         }
832
833                                         nu = nu->next;
834                                 }
835                         }
836                 }
837
838                 currkey = cu->key->block.first;
839                 while (currkey) {
840                         int apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative));
841
842                         float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert,  "currkey->data");
843                         ofp = oldkey = currkey->data;
844
845                         nu = editnurb->nurbs.first;
846                         i = 0;
847                         while (nu) {
848                                 if (currkey == actkey) {
849                                         int restore = actkey != cu->key->refkey;
850
851                                         if (nu->bezt) {
852                                                 bezt = nu->bezt;
853                                                 a = nu->pntsu;
854                                                 while (a--) {
855                                                         int j;
856                                                         oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
857
858                                                         for (j = 0; j < 3; ++j, ++i) {
859                                                                 copy_v3_v3(fp, bezt->vec[j]);
860
861                                                                 if (restore && oldbezt) {
862                                                                         copy_v3_v3(bezt->vec[j], oldbezt->vec[j]);
863                                                                 }
864
865                                                                 fp += 3;
866                                                         }
867                                                         fp[0] = bezt->alfa;
868
869                                                         if (restore && oldbezt) {
870                                                                 bezt->alfa = oldbezt->alfa;
871                                                         }
872
873                                                         fp += 3; ++i; /* alphas */
874                                                         bezt++;
875                                                 }
876                                         }
877                                         else {
878                                                 bp = nu->bp;
879                                                 a = nu->pntsu * nu->pntsv;
880                                                 while (a--) {
881                                                         oldbp = getKeyIndexOrig_bp(editnurb, bp);
882
883                                                         copy_v3_v3(fp, bp->vec);
884
885                                                         fp[3] = bp->alfa;
886
887                                                         if (restore && oldbp) {
888                                                                 copy_v3_v3(bp->vec, oldbp->vec);
889                                                                 bp->alfa = oldbp->alfa;
890                                                         }
891
892                                                         fp += 4;
893                                                         bp++;
894                                                         i += 2;
895                                                 }
896                                         }
897                                 }
898                                 else {
899                                         int index;
900                                         const float *curofp;
901
902                                         if (oldkey) {
903                                                 if (nu->bezt) {
904                                                         bezt = nu->bezt;
905                                                         a = nu->pntsu;
906
907                                                         while (a--) {
908                                                                 index = getKeyIndexOrig_keyIndex(editnurb, bezt);
909                                                                 if (index >= 0) {
910                                                                         int j;
911                                                                         curofp = ofp + index;
912
913                                                                         for (j = 0; j < 3; ++j, ++i) {
914                                                                                 copy_v3_v3(fp, curofp);
915
916                                                                                 if (apply_offset) {
917                                                                                         add_v3_v3(fp, ofs[i]);
918                                                                                 }
919
920                                                                                 fp += 3; curofp += 3;
921                                                                         }
922                                                                         fp[0] = curofp[0];
923
924                                                                         if (apply_offset) {
925                                                                                 /* apply alfa offsets */
926                                                                                 add_v3_v3(fp, ofs[i]);
927                                                                                 i++;
928                                                                         }
929
930                                                                         fp += 3; /* alphas */
931                                                                 }
932                                                                 else {
933                                                                         int j;
934                                                                         for (j = 0; j < 3; ++j, ++i) {
935                                                                                 copy_v3_v3(fp, bezt->vec[j]);
936                                                                                 fp += 3;
937                                                                         }
938                                                                         fp[0] = bezt->alfa;
939
940                                                                         fp += 3; /* alphas */
941                                                                 }
942                                                                 bezt++;
943                                                         }
944                                                 }
945                                                 else {
946                                                         bp = nu->bp;
947                                                         a = nu->pntsu * nu->pntsv;
948                                                         while (a--) {
949                                                                 index = getKeyIndexOrig_keyIndex(editnurb, bp);
950
951                                                                 if (index >= 0) {
952                                                                         curofp = ofp + index;
953                                                                         copy_v3_v3(fp, curofp);
954                                                                         fp[3] = curofp[3];
955
956                                                                         if (apply_offset) {
957                                                                                 add_v3_v3(fp, ofs[i]);
958                                                                                 fp[3] += ofs[i + 1][0];
959                                                                         }
960                                                                 }
961                                                                 else {
962                                                                         copy_v3_v3(fp, bp->vec);
963                                                                         fp[3] = bp->alfa;
964                                                                 }
965
966                                                                 fp += 4;
967                                                                 bp++;
968                                                                 i += 2;
969                                                         }
970                                                 }
971                                         }
972                                 }
973
974                                 nu = nu->next;
975                         }
976
977                         if (apply_offset) {
978                                 /* handles could become malicious after offsets applying */
979                                 calc_keyHandles(&editnurb->nurbs, newkey);
980                         }
981
982                         currkey->totelem = totvert;
983                         if (currkey->data) MEM_freeN(currkey->data);
984                         currkey->data = newkey;
985
986                         currkey = currkey->next;
987                 }
988
989                 if (ofs) MEM_freeN(ofs);
990         }
991 }
992
993 /* ********************* Amimation data *************** */
994
995 static bool curve_is_animated(Curve *cu)
996 {
997         AnimData *ad = BKE_animdata_from_id(&cu->id);
998
999         return ad && (ad->action || ad->drivers.first);
1000 }
1001
1002 static void fcurve_path_rename(AnimData *adt, const char *orig_rna_path, char *rna_path,
1003                                ListBase *orig_curves, ListBase *curves)
1004 {
1005         FCurve *fcu, *nfcu, *nextfcu;
1006         int len = strlen(orig_rna_path);
1007
1008         for (fcu = orig_curves->first; fcu; fcu = nextfcu) {
1009                 nextfcu = fcu->next;
1010                 if (!strncmp(fcu->rna_path, orig_rna_path, len)) {
1011                         char *spath, *suffix = fcu->rna_path + len;
1012                         nfcu = copy_fcurve(fcu);
1013                         spath = nfcu->rna_path;
1014                         nfcu->rna_path = BLI_sprintfN("%s%s", rna_path, suffix);
1015                         BLI_addtail(curves, nfcu);
1016
1017                         if (fcu->grp) {
1018                                 action_groups_remove_channel(adt->action, fcu);
1019                                 action_groups_add_channel(adt->action, fcu->grp, nfcu);
1020                         }
1021                         else if ((adt->action) && (&adt->action->curves == orig_curves))
1022                                 BLI_remlink(&adt->action->curves, fcu);
1023                         else
1024                                 BLI_remlink(&adt->drivers, fcu);
1025
1026                         free_fcurve(fcu);
1027
1028                         MEM_freeN(spath);
1029                 }
1030         }
1031 }
1032
1033 static void fcurve_remove(AnimData *adt, ListBase *orig_curves, FCurve *fcu)
1034 {
1035         if (orig_curves == &adt->drivers) BLI_remlink(&adt->drivers, fcu);
1036         else action_groups_remove_channel(adt->action, fcu);
1037
1038         free_fcurve(fcu);
1039 }
1040
1041 static void curve_rename_fcurves(Curve *cu, ListBase *orig_curves)
1042 {
1043         int nu_index = 0, a, pt_index;
1044         EditNurb *editnurb = cu->editnurb;
1045         Nurb *nu = editnurb->nurbs.first;
1046         CVKeyIndex *keyIndex;
1047         char rna_path[64], orig_rna_path[64];
1048         AnimData *adt = BKE_animdata_from_id(&cu->id);
1049         ListBase curves = {NULL, NULL};
1050         FCurve *fcu, *next;
1051
1052         for (nu = editnurb->nurbs.first, nu_index = 0;  nu != NULL;  nu = nu->next, nu_index++) {
1053                 if (nu->bezt) {
1054                         BezTriple *bezt = nu->bezt;
1055                         a = nu->pntsu;
1056                         pt_index = 0;
1057
1058                         while (a--) {
1059                                 keyIndex = getCVKeyIndex(editnurb, bezt);
1060                                 if (keyIndex) {
1061                                         BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].bezier_points[%d]", nu_index, pt_index);
1062                                         BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].bezier_points[%d]", keyIndex->nu_index, keyIndex->pt_index);
1063
1064                                         if (keyIndex->switched) {
1065                                                 char handle_path[64], orig_handle_path[64];
1066                                                 BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_left", orig_rna_path);
1067                                                 BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_right", rna_path);
1068                                                 fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves);
1069
1070                                                 BLI_snprintf(orig_handle_path, sizeof(orig_rna_path), "%s.handle_right", orig_rna_path);
1071                                                 BLI_snprintf(handle_path, sizeof(rna_path), "%s.handle_left", rna_path);
1072                                                 fcurve_path_rename(adt, orig_handle_path, handle_path, orig_curves, &curves);
1073                                         }
1074
1075                                         fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
1076
1077                                         keyIndex->nu_index = nu_index;
1078                                         keyIndex->pt_index = pt_index;
1079                                 }
1080
1081                                 bezt++;
1082                                 pt_index++;
1083                         }
1084                 }
1085                 else {
1086                         BPoint *bp = nu->bp;
1087                         a = nu->pntsu * nu->pntsv;
1088                         pt_index = 0;
1089
1090                         while (a--) {
1091                                 keyIndex = getCVKeyIndex(editnurb, bp);
1092                                 if (keyIndex) {
1093                                         BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d].points[%d]", nu_index, pt_index);
1094                                         BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d].points[%d]", keyIndex->nu_index, keyIndex->pt_index);
1095                                         fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
1096
1097                                         keyIndex->nu_index = nu_index;
1098                                         keyIndex->pt_index = pt_index;
1099                                 }
1100
1101                                 bp++;
1102                                 pt_index++;
1103                         }
1104                 }
1105         }
1106
1107         /* remove paths for removed control points
1108          * need this to make further step with copying non-cv related curves copying
1109          * not touching cv's f-curves */
1110         for (fcu = orig_curves->first; fcu; fcu = next) {
1111                 next = fcu->next;
1112
1113                 if (!strncmp(fcu->rna_path, "splines", 7)) {
1114                         const char *ch = strchr(fcu->rna_path, '.');
1115
1116                         if (ch && (!strncmp(ch, ".bezier_points", 14) || !strncmp(ch, ".points", 7)))
1117                                 fcurve_remove(adt, orig_curves, fcu);
1118                 }
1119         }
1120
1121         for (nu = editnurb->nurbs.first, nu_index = 0;  nu != NULL;  nu = nu->next, nu_index++) {
1122                 keyIndex = NULL;
1123                 if (nu->pntsu) {
1124                         if (nu->bezt) keyIndex = getCVKeyIndex(editnurb, &nu->bezt[0]);
1125                         else keyIndex = getCVKeyIndex(editnurb, &nu->bp[0]);
1126                 }
1127
1128                 if (keyIndex) {
1129                         BLI_snprintf(rna_path, sizeof(rna_path), "splines[%d]", nu_index);
1130                         BLI_snprintf(orig_rna_path, sizeof(orig_rna_path), "splines[%d]", keyIndex->nu_index);
1131                         fcurve_path_rename(adt, orig_rna_path, rna_path, orig_curves, &curves);
1132                 }
1133         }
1134
1135         /* the remainders in orig_curves can be copied back (like follow path) */
1136         /* (if it's not path to spline) */
1137         for (fcu = orig_curves->first; fcu; fcu = next) {
1138                 next = fcu->next;
1139
1140                 if (!strncmp(fcu->rna_path, "splines", 7)) fcurve_remove(adt, orig_curves, fcu);
1141                 else BLI_addtail(&curves, fcu);
1142         }
1143
1144         *orig_curves = curves;
1145 }
1146
1147 /* return 0 if animation data wasn't changed, 1 otherwise */
1148 int ED_curve_updateAnimPaths(Curve *cu)
1149 {
1150         AnimData *adt = BKE_animdata_from_id(&cu->id);
1151         EditNurb *editnurb = cu->editnurb;
1152
1153         if (!editnurb->keyindex)
1154                 return 0;
1155
1156         if (!curve_is_animated(cu)) return 0;
1157
1158         if (adt->action)
1159                 curve_rename_fcurves(cu, &adt->action->curves);
1160
1161         curve_rename_fcurves(cu, &adt->drivers);
1162
1163         return 1;
1164 }
1165
1166 /* ********************* LOAD and MAKE *************** */
1167
1168 static int *initialize_index_map(Object *obedit, int *r_old_totvert)
1169 {
1170         Curve *curve = (Curve *) obedit->data;
1171         EditNurb *editnurb = curve->editnurb;
1172         Nurb *nu;
1173         CVKeyIndex *keyIndex;
1174         int *old_to_new_map;
1175         int old_totvert, i;
1176         int vertex_index;
1177
1178         for (nu = curve->nurb.first, old_totvert = 0; nu != NULL; nu = nu->next) {
1179                 if (nu->bezt) {
1180                         old_totvert += nu->pntsu * 3;
1181                 }
1182                 else {
1183                         old_totvert += nu->pntsu * nu->pntsv;
1184                 }
1185         }
1186
1187         old_to_new_map = MEM_mallocN(old_totvert * sizeof(int), "curve old to new index map");
1188         for (i = 0; i < old_totvert; i++) {
1189                 old_to_new_map[i] = -1;
1190         }
1191
1192         for (nu = editnurb->nurbs.first, vertex_index = 0;
1193              nu != NULL;
1194              nu = nu->next, vertex_index++)
1195         {
1196                 if (nu->bezt) {
1197                         BezTriple *bezt = nu->bezt;
1198                         int a = nu->pntsu;
1199
1200                         while (a--) {
1201                                 keyIndex = getCVKeyIndex(editnurb, bezt);
1202                                 if (keyIndex) {
1203                                         if (keyIndex->switched) {
1204                                                 old_to_new_map[keyIndex->vertex_index] = vertex_index + 2;
1205                                                 old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
1206                                                 old_to_new_map[keyIndex->vertex_index + 2] = vertex_index;
1207                                         }
1208                                         else {
1209                                                 old_to_new_map[keyIndex->vertex_index] = vertex_index;
1210                                                 old_to_new_map[keyIndex->vertex_index + 1] = vertex_index + 1;
1211                                                 old_to_new_map[keyIndex->vertex_index + 2] = vertex_index + 2;
1212                                         }
1213                                 }
1214                                 vertex_index += 3;
1215                                 bezt++;
1216                         }
1217                 }
1218                 else {
1219                         BPoint *bp = nu->bp;
1220                         int a = nu->pntsu * nu->pntsv;
1221
1222                         while (a--) {
1223                                 keyIndex = getCVKeyIndex(editnurb, bp);
1224                                 if (keyIndex) {
1225                                         old_to_new_map[keyIndex->vertex_index] = vertex_index;
1226                                 }
1227                                 vertex_index++;
1228                                 bp++;
1229                         }
1230                 }
1231         }
1232
1233         *r_old_totvert = old_totvert;
1234         return old_to_new_map;
1235 }
1236
1237 static void remap_hooks_and_vertex_parents(Object *obedit)
1238 {
1239         Object *object;
1240         Curve *curve = (Curve *) obedit->data;
1241         int *old_to_new_map = NULL;
1242         int old_totvert;
1243
1244         for (object = G.main->object.first; object; object = object->id.next) {
1245                 ModifierData *md;
1246                 int index;
1247                 if ((object->parent) &&
1248                     (object->parent->data == curve) &&
1249                     ELEM(object->partype, PARVERT1, PARVERT3))
1250                 {
1251                         if (old_to_new_map == NULL) {
1252                                 old_to_new_map = initialize_index_map(obedit, &old_totvert);
1253                         }
1254
1255                         if (object->par1 < old_totvert) {
1256                                 index = old_to_new_map[object->par1];
1257                                 if (index != -1) {
1258                                         object->par1 = index;
1259                                 }
1260                         }
1261                         if (object->par2 < old_totvert) {
1262                                 index = old_to_new_map[object->par2];
1263                                 if (index != -1) {
1264                                         object->par2 = index;
1265                                 }
1266                         }
1267                         if (object->par3 < old_totvert) {
1268                                 index = old_to_new_map[object->par3];
1269                                 if (index != -1) {
1270                                         object->par3 = index;
1271                                 }
1272                         }
1273                 }
1274                 if (object->data == curve) {
1275                         for (md = object->modifiers.first; md; md = md->next) {
1276                                 if (md->type == eModifierType_Hook) {
1277                                         HookModifierData *hmd = (HookModifierData *) md;
1278                                         int i, j;
1279
1280                                         if (old_to_new_map == NULL) {
1281                                                 old_to_new_map = initialize_index_map(obedit, &old_totvert);
1282                                         }
1283
1284                                         for (i = j = 0; i < hmd->totindex; i++) {
1285                                                 if (hmd->indexar[i] < old_totvert) {
1286                                                         index = old_to_new_map[hmd->indexar[i]];
1287                                                         if (index != -1) {
1288                                                                 hmd->indexar[j++] = index;
1289                                                         }
1290                                                 }
1291                                                 else {
1292                                                         j++;
1293                                                 }
1294                                         }
1295
1296                                         hmd->totindex = j;
1297                                 }
1298                         }
1299                 }
1300         }
1301         if (old_to_new_map != NULL) {
1302                 MEM_freeN(old_to_new_map);
1303         }
1304 }
1305
1306 /* load editNurb in object */
1307 void load_editNurb(Object *obedit)
1308 {
1309         ListBase *editnurb = object_editcurve_get(obedit);
1310
1311         if (obedit == NULL) return;
1312
1313         if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
1314                 Curve *cu = obedit->data;
1315                 Nurb *nu, *newnu;
1316                 ListBase newnurb = {NULL, NULL}, oldnurb = cu->nurb;
1317
1318                 remap_hooks_and_vertex_parents(obedit);
1319
1320                 for (nu = editnurb->first; nu; nu = nu->next) {
1321                         newnu = BKE_nurb_duplicate(nu);
1322                         BLI_addtail(&newnurb, newnu);
1323
1324                         if (nu->type == CU_NURBS) {
1325                                 BKE_nurb_order_clamp_u(nu);
1326                         }
1327                 }
1328
1329                 cu->nurb = newnurb;
1330
1331                 calc_shapeKeys(obedit);
1332                 ED_curve_updateAnimPaths(obedit->data);
1333
1334                 BKE_nurbList_free(&oldnurb);
1335         }
1336 }
1337
1338 /* make copy in cu->editnurb */
1339 void make_editNurb(Object *obedit)
1340 {
1341         Curve *cu = (Curve *)obedit->data;
1342         EditNurb *editnurb = cu->editnurb;
1343         Nurb *nu, *newnu;
1344         KeyBlock *actkey;
1345
1346         if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
1347                 actkey = BKE_keyblock_from_object(obedit);
1348
1349                 if (actkey) {
1350                         // XXX strcpy(G.editModeTitleExtra, "(Key) ");
1351                         undo_editmode_clear();
1352                         BKE_key_convert_to_curve(actkey, cu, &cu->nurb);
1353                 }
1354
1355                 if (editnurb) {
1356                         BKE_nurbList_free(&editnurb->nurbs);
1357                         BKE_curve_editNurb_keyIndex_free(editnurb);
1358                         editnurb->keyindex = NULL;
1359                 }
1360                 else {
1361                         editnurb = MEM_callocN(sizeof(EditNurb), "editnurb");
1362                         cu->editnurb = editnurb;
1363                 }
1364
1365                 nu = cu->nurb.first;
1366                 while (nu) {
1367                         newnu = BKE_nurb_duplicate(nu);
1368                         BKE_nurb_test2D(newnu); // after join, or any other creation of curve
1369                         BLI_addtail(&editnurb->nurbs, newnu);
1370                         nu = nu->next;
1371                 }
1372
1373                 if (actkey)
1374                         editnurb->shapenr = obedit->shapenr;
1375
1376                 /* animation could be added in editmode even if there was no animdata in
1377                  * object mode hence we always need CVs index be created */
1378                 init_editNurb_keyIndex(editnurb, &cu->nurb);
1379         }
1380 }
1381
1382 void free_editNurb(Object *obedit)
1383 {
1384         Curve *cu = obedit->data;
1385
1386         BKE_curve_editNurb_free(cu);
1387 }
1388
1389 void ED_curve_deselect_all(EditNurb *editnurb)
1390 {
1391         Nurb *nu;
1392         int a;
1393
1394         for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
1395                 if (nu->bezt) {
1396                         BezTriple *bezt;
1397                         for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
1398                                 bezt->f1 &= ~SELECT;
1399                                 bezt->f2 &= ~SELECT;
1400                                 bezt->f3 &= ~SELECT;
1401                         }
1402                 }
1403                 else if (nu->bp) {
1404                         BPoint *bp;
1405                         for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
1406                                 bp->f1 &= ~SELECT;
1407                         }
1408                 }
1409         }
1410 }
1411
1412 void ED_curve_select_all(EditNurb *editnurb)
1413 {
1414         Nurb *nu;
1415         int a;
1416         for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
1417                 if (nu->bezt) {
1418                         BezTriple *bezt;
1419                         for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
1420                                 if (bezt->hide == 0) {
1421                                         bezt->f1 |= SELECT;
1422                                         bezt->f2 |= SELECT;
1423                                         bezt->f3 |= SELECT;
1424                                 }
1425                         }
1426                 }
1427                 else if (nu->bp) {
1428                         BPoint *bp;
1429                         for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
1430                                 if (bp->hide == 0)
1431                                         bp->f1 |= SELECT;
1432                         }
1433                 }
1434         }
1435 }
1436
1437 void ED_curve_select_swap(EditNurb *editnurb, bool hide_handles)
1438 {
1439         Nurb *nu;
1440         BPoint *bp;
1441         BezTriple *bezt;
1442         int a;
1443
1444         for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
1445                 if (nu->type == CU_BEZIER) {
1446                         bezt = nu->bezt;
1447                         a = nu->pntsu;
1448                         while (a--) {
1449                                 if (bezt->hide == 0) {
1450                                         bezt->f2 ^= SELECT; /* always do the center point */
1451                                         if (!hide_handles) {
1452                                                 bezt->f1 ^= SELECT;
1453                                                 bezt->f3 ^= SELECT;
1454                                         }
1455                                 }
1456                                 bezt++;
1457                         }
1458                 }
1459                 else {
1460                         bp = nu->bp;
1461                         a = nu->pntsu * nu->pntsv;
1462                         while (a--) {
1463                                 swap_selection_bpoint(bp);
1464                                 bp++;
1465                         }
1466                 }
1467         }
1468 }
1469
1470 /******************** transform operator **********************/
1471
1472 void ED_curve_transform(Curve *cu, float mat[4][4])
1473 {
1474         Nurb *nu;
1475         BPoint *bp;
1476         BezTriple *bezt;
1477         int a;
1478
1479         float scale = mat4_to_scale(mat);
1480
1481         for (nu = cu->nurb.first; nu; nu = nu->next) {
1482                 if (nu->type == CU_BEZIER) {
1483                         a = nu->pntsu;
1484                         for (bezt = nu->bezt; a--; bezt++) {
1485                                 mul_m4_v3(mat, bezt->vec[0]);
1486                                 mul_m4_v3(mat, bezt->vec[1]);
1487                                 mul_m4_v3(mat, bezt->vec[2]);
1488                                 bezt->radius *= scale;
1489                         }
1490                         BKE_nurb_handles_calc(nu);
1491                 }
1492                 else {
1493                         a = nu->pntsu * nu->pntsv;
1494                         for (bp = nu->bp; a--; bp++)
1495                                 mul_m4_v3(mat, bp->vec);
1496                 }
1497         }
1498         DAG_id_tag_update(&cu->id, 0);
1499 }
1500
1501 /******************** separate operator ***********************/
1502
1503 static int separate_exec(bContext *C, wmOperator *op)
1504 {
1505         Main *bmain = CTX_data_main(C);
1506         Scene *scene = CTX_data_scene(C);
1507         Object *oldob, *newob;
1508         Base *oldbase, *newbase;
1509         Curve *oldcu, *newcu;
1510         EditNurb *newedit;
1511         ListBase newnurb = {NULL, NULL};
1512
1513         oldbase = CTX_data_active_base(C);
1514         oldob = oldbase->object;
1515         oldcu = oldob->data;
1516
1517         if (oldcu->key) {
1518                 BKE_report(op->reports, RPT_ERROR, "Cannot separate a curve with vertex keys");
1519                 return OPERATOR_CANCELLED;
1520         }
1521
1522         WM_cursor_wait(1);
1523
1524         /* 1. duplicate geometry and check for valid selection for separate */
1525         adduplicateflagNurb(oldob, &newnurb, SELECT, true);
1526
1527         if (BLI_listbase_is_empty(&newnurb)) {
1528                 WM_cursor_wait(0);
1529                 BKE_report(op->reports, RPT_ERROR, "Cannot separate current selection");
1530                 return OPERATOR_CANCELLED;
1531         }
1532
1533         /* 2. duplicate the object and data */
1534         newbase = ED_object_add_duplicate(bmain, scene, oldbase, 0); /* 0 = fully linked */
1535         DAG_relations_tag_update(bmain);
1536
1537         newob = newbase->object;
1538         newcu = newob->data = BKE_curve_copy(oldcu);
1539         newcu->editnurb = NULL;
1540         oldcu->id.us--; /* because new curve is a copy: reduce user count */
1541
1542         /* 3. put new object in editmode, clear it and set separated nurbs */
1543         make_editNurb(newob);
1544         newedit = newcu->editnurb;
1545         BKE_nurbList_free(&newedit->nurbs);
1546         BKE_curve_editNurb_keyIndex_free(newedit);
1547         newedit->keyindex = NULL;
1548         BLI_movelisttolist(&newedit->nurbs, &newnurb);
1549
1550         /* 4. put old object out of editmode and delete separated geometry */
1551         load_editNurb(newob);
1552         free_editNurb(newob);
1553         curve_delete_segments(oldob, true);
1554
1555         DAG_id_tag_update(&oldob->id, OB_RECALC_DATA);  /* this is the original one */
1556         DAG_id_tag_update(&newob->id, OB_RECALC_DATA);  /* this is the separated one */
1557
1558         WM_event_add_notifier(C, NC_GEOM | ND_DATA, oldob->data);
1559         WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, newob);
1560
1561         WM_cursor_wait(0);
1562
1563         return OPERATOR_FINISHED;
1564 }
1565
1566 void CURVE_OT_separate(wmOperatorType *ot)
1567 {
1568         /* identifiers */
1569         ot->name = "Separate";
1570         ot->idname = "CURVE_OT_separate";
1571         ot->description = "Separate selected points from connected unselected points into a new object";
1572         
1573         /* api callbacks */
1574         ot->exec = separate_exec;
1575         ot->poll = ED_operator_editsurfcurve;
1576         
1577         /* flags */
1578         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1579 }
1580
1581 /******************** split operator ***********************/
1582
1583 static int curve_split_exec(bContext *C, wmOperator *op)
1584 {
1585         Object *obedit = CTX_data_edit_object(C);
1586         ListBase *editnurb = object_editcurve_get(obedit);
1587         ListBase newnurb = {NULL, NULL};
1588
1589         adduplicateflagNurb(obedit, &newnurb, SELECT, true);
1590
1591         if (BLI_listbase_is_empty(&newnurb) == false) {
1592                 curve_delete_segments(obedit, true);
1593                 BLI_movelisttolist(editnurb, &newnurb);
1594
1595                 if (ED_curve_updateAnimPaths(obedit->data))
1596                         WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
1597
1598                 WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
1599                 DAG_id_tag_update(obedit->data, 0);
1600         }
1601         else {
1602                 BKE_report(op->reports, RPT_ERROR, "Cannot split current selection");
1603                 return OPERATOR_CANCELLED;
1604         }
1605
1606         return OPERATOR_FINISHED;
1607 }
1608
1609 void CURVE_OT_split(wmOperatorType *ot)
1610 {
1611         /* identifiers */
1612         ot->name = "Split";
1613         ot->idname = "CURVE_OT_split";
1614         ot->description = "Split off selected points from connected unselected points";
1615
1616         /* api callbacks */
1617         ot->exec = curve_split_exec;
1618         ot->poll = ED_operator_editsurfcurve;
1619
1620         /* flags */
1621         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1622 }
1623
1624 /* ******************* FLAGS ********************* */
1625
1626 static short isNurbselUV(Nurb *nu, int *u, int *v, int flag)
1627 {
1628         /* return (u != -1): 1 row in u-direction selected. U has value between 0-pntsv
1629          * return (v != -1): 1 column in v-direction selected. V has value between 0-pntsu
1630          */
1631         BPoint *bp;
1632         int a, b, sel;
1633
1634         *u = *v = -1;
1635
1636         bp = nu->bp;
1637         for (b = 0; b < nu->pntsv; b++) {
1638                 sel = 0;
1639                 for (a = 0; a < nu->pntsu; a++, bp++) {
1640                         if (bp->f1 & flag) sel++;
1641                 }
1642                 if (sel == nu->pntsu) {
1643                         if (*u == -1) *u = b;
1644                         else return 0;
1645                 }
1646                 else if (sel > 1) {
1647                         return 0;  /* because sel == 1 is still ok */
1648                 }
1649         }
1650
1651         for (a = 0; a < nu->pntsu; a++) {
1652                 sel = 0;
1653                 bp = &nu->bp[a];
1654                 for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
1655                         if (bp->f1 & flag) sel++;
1656                 }
1657                 if (sel == nu->pntsv) {
1658                         if (*v == -1) *v = a;
1659                         else return 0;
1660                 }
1661                 else if (sel > 1) {
1662                         return 0;
1663                 }
1664         }
1665
1666         if (*u == -1 && *v > -1) return 1;
1667         if (*v == -1 && *u > -1) return 1;
1668         return 0;
1669 }
1670
1671 /* return true if U direction is selected and number of selected columns v */
1672 static bool isNurbselU(Nurb *nu, int *v, int flag)
1673 {
1674         BPoint *bp;
1675         int a, b, sel;
1676
1677         *v = 0;
1678
1679         for (b = 0, bp = nu->bp; b < nu->pntsv; b++) {
1680                 sel = 0;
1681                 for (a = 0; a < nu->pntsu; a++, bp++) {
1682                         if (bp->f1 & flag) sel++;
1683                 }
1684                 if (sel == nu->pntsu) {
1685                         (*v)++;
1686                 }
1687                 else if (sel >= 1) {
1688                         *v = 0;
1689                         return 0;
1690                 }
1691         }
1692
1693         return 1;
1694 }
1695
1696 /* return true if V direction is selected and number of selected rows u */
1697 static bool isNurbselV(Nurb *nu, int *u, int flag)
1698 {
1699         BPoint *bp;
1700         int a, b, sel;
1701
1702         *u = 0;
1703
1704         for (a = 0; a < nu->pntsu; a++) {
1705                 bp = &nu->bp[a];
1706                 sel = 0;
1707                 for (b = 0; b < nu->pntsv; b++, bp += nu->pntsu) {
1708                         if (bp->f1 & flag) sel++;
1709                 }
1710                 if (sel == nu->pntsv) {
1711                         (*u)++;
1712                 }
1713                 else if (sel >= 1) {
1714                         *u = 0;
1715                         return 0;
1716                 }
1717         }
1718
1719         return 1;
1720 }
1721
1722 static void rotateflagNurb(ListBase *editnurb, short flag, const float cent[3], float rotmat[3][3])
1723 {
1724         /* all verts with (flag & 'flag') rotate */
1725         Nurb *nu;
1726         BPoint *bp;
1727         int a;
1728
1729         for (nu = editnurb->first; nu; nu = nu->next) {
1730                 if (nu->type == CU_NURBS) {
1731                         bp = nu->bp;
1732                         a = nu->pntsu * nu->pntsv;
1733
1734                         while (a--) {
1735                                 if (bp->f1 & flag) {
1736                                         sub_v3_v3(bp->vec, cent);
1737                                         mul_m3_v3(rotmat, bp->vec);
1738                                         add_v3_v3(bp->vec, cent);
1739                                 }
1740                                 bp++;
1741                         }
1742                 }
1743         }
1744 }
1745
1746 void ed_editnurb_translate_flag(ListBase *editnurb, short flag, const float vec[3])
1747 {
1748         /* all verts with ('flag' & flag) translate */
1749         Nurb *nu;
1750         BezTriple *bezt;
1751         BPoint *bp;
1752         int a;
1753
1754         for (nu = editnurb->first; nu; nu = nu->next) {
1755                 if (nu->type == CU_BEZIER) {
1756                         a = nu->pntsu;
1757                         bezt = nu->bezt;
1758                         while (a--) {
1759                                 if (bezt->f1 & flag) add_v3_v3(bezt->vec[0], vec);
1760                                 if (bezt->f2 & flag) add_v3_v3(bezt->vec[1], vec);
1761                                 if (bezt->f3 & flag) add_v3_v3(bezt->vec[2], vec);
1762                                 bezt++;
1763                         }
1764                 }
1765                 else {
1766                         a = nu->pntsu * nu->pntsv;
1767                         bp = nu->bp;
1768                         while (a--) {
1769                                 if (bp->f1 & flag) add_v3_v3(bp->vec, vec);
1770                                 bp++;
1771                         }
1772                 }
1773
1774                 BKE_nurb_test2D(nu);
1775         }
1776 }
1777
1778 static void weightflagNurb(ListBase *editnurb, short flag, float w)
1779 {
1780         Nurb *nu;
1781         BPoint *bp;
1782         int a;
1783
1784         for (nu = editnurb->first; nu; nu = nu->next) {
1785                 if (nu->type == CU_NURBS) {
1786                         a = nu->pntsu * nu->pntsv;
1787                         bp = nu->bp;
1788                         while (a--) {
1789                                 if (bp->f1 & flag) {
1790                                         /* a mode used to exist for replace/multiple but is was unused */
1791                                         bp->vec[3] *= w;
1792                                 }
1793                                 bp++;
1794                         }
1795                 }
1796         }
1797 }
1798
1799 static void ed_surf_delete_selected(Object *obedit)
1800 {
1801         Curve *cu = obedit->data;
1802         ListBase *editnurb = object_editcurve_get(obedit);
1803         Nurb *nu, *next;
1804         BPoint *bp, *bpn, *newbp;
1805         int a, b, newu, newv;
1806
1807         BLI_assert(obedit->type == OB_SURF);
1808
1809         nu = editnurb->first;
1810         while (nu) {
1811                 next = nu->next;
1812
1813                 /* is entire nurb selected */
1814                 bp = nu->bp;
1815                 a = nu->pntsu * nu->pntsv;
1816                 while (a) {
1817                         a--;
1818                         if (bp->f1 & SELECT) {
1819                                 /* pass */
1820                         }
1821                         else {
1822                                 break;
1823                         }
1824                         bp++;
1825                 }
1826                 if (a == 0) {
1827                         BLI_remlink(editnurb, nu);
1828                         keyIndex_delNurb(cu->editnurb, nu);
1829                         BKE_nurb_free(nu); nu = NULL;
1830                 }
1831                 else {
1832                         if (isNurbselU(nu, &newv, SELECT)) {
1833                                 /* U direction selected */
1834                                 newv = nu->pntsv - newv;
1835                                 if (newv != nu->pntsv) {
1836                                         /* delete */
1837                                         bp = nu->bp;
1838                                         bpn = newbp = (BPoint *)MEM_mallocN(newv * nu->pntsu * sizeof(BPoint), "deleteNurb");
1839                                         for (b = 0; b < nu->pntsv; b++) {
1840                                                 if ((bp->f1 & SELECT) == 0) {
1841                                                         memcpy(bpn, bp, nu->pntsu * sizeof(BPoint));
1842                                                         keyIndex_updateBP(cu->editnurb, bp, bpn, nu->pntsu);
1843                                                         bpn += nu->pntsu;
1844                                                 }
1845                                                 else {
1846                                                         keyIndex_delBP(cu->editnurb, bp);
1847                                                 }
1848                                                 bp += nu->pntsu;
1849                                         }
1850                                         nu->pntsv = newv;
1851                                         MEM_freeN(nu->bp);
1852                                         nu->bp = newbp;
1853                                         BKE_nurb_order_clamp_v(nu);
1854
1855                                         BKE_nurb_knot_calc_v(nu);
1856                                 }
1857                         }
1858                         else if (isNurbselV(nu, &newu, SELECT)) {
1859                                 /* V direction selected */
1860                                 newu = nu->pntsu - newu;
1861                                 if (newu != nu->pntsu) {
1862                                         /* delete */
1863                                         bp = nu->bp;
1864                                         bpn = newbp = (BPoint *)MEM_mallocN(newu * nu->pntsv * sizeof(BPoint), "deleteNurb");
1865                                         for (b = 0; b < nu->pntsv; b++) {
1866                                                 for (a = 0; a < nu->pntsu; a++, bp++) {
1867                                                         if ((bp->f1 & SELECT) == 0) {
1868                                                                 *bpn = *bp;
1869                                                                 keyIndex_updateBP(cu->editnurb, bp, bpn, 1);
1870                                                                 bpn++;
1871                                                         }
1872                                                         else {
1873                                                                 keyIndex_delBP(cu->editnurb, bp);
1874                                                         }
1875                                                 }
1876                                         }
1877                                         MEM_freeN(nu->bp);
1878                                         nu->bp = newbp;
1879                                         if (newu == 1 && nu->pntsv > 1) {    /* make a U spline */
1880                                                 nu->pntsu = nu->pntsv;
1881                                                 nu->pntsv = 1;
1882                                                 SWAP(short, nu->orderu, nu->orderv);
1883                                                 BKE_nurb_order_clamp_u(nu);
1884                                                 if (nu->knotsv) MEM_freeN(nu->knotsv);
1885                                                 nu->knotsv = NULL;
1886                                         }
1887                                         else {
1888                                                 nu->pntsu = newu;
1889                                                 BKE_nurb_order_clamp_u(nu);
1890                                         }
1891                                         BKE_nurb_knot_calc_u(nu);
1892                                 }
1893                         }
1894                 }
1895                 nu = next;
1896         }
1897 }
1898
1899 static void ed_curve_delete_selected(Object *obedit)
1900 {
1901         Curve *cu = obedit->data;
1902         EditNurb *editnurb = cu->editnurb;
1903         ListBase *nubase = &editnurb->nurbs;
1904         Nurb *nu, *next;
1905         BezTriple *bezt, *bezt1;
1906         BPoint *bp, *bp1;
1907         int a, type, nuindex = 0;
1908
1909         /* first loop, can we remove entire pieces? */
1910         nu = nubase->first;
1911         while (nu) {
1912                 next = nu->next;
1913                 if (nu->type == CU_BEZIER) {
1914                         bezt = nu->bezt;
1915                         a = nu->pntsu;
1916                         if (a) {
1917                                 while (a) {
1918                                         if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
1919                                                 /* pass */
1920                                         }
1921                                         else {
1922                                                 break;
1923                                         }
1924                                         a--;
1925                                         bezt++;
1926                                 }
1927                                 if (a == 0) {
1928                                         if (cu->actnu == nuindex)
1929                                                 cu->actnu = CU_ACT_NONE;
1930
1931                                         BLI_remlink(nubase, nu);
1932                                         keyIndex_delNurb(editnurb, nu);
1933                                         BKE_nurb_free(nu); nu = NULL;
1934                                 }
1935                         }
1936                 }
1937                 else {
1938                         bp = nu->bp;
1939                         a = nu->pntsu * nu->pntsv;
1940                         if (a) {
1941                                 while (a) {
1942                                         if (bp->f1 & SELECT) {
1943                                                 /* pass */
1944                                         }
1945                                         else {
1946                                                 break;
1947                                         }
1948                                         a--;
1949                                         bp++;
1950                                 }
1951                                 if (a == 0) {
1952                                         if (cu->actnu == nuindex)
1953                                                 cu->actnu = CU_ACT_NONE;
1954
1955                                         BLI_remlink(nubase, nu);
1956                                         keyIndex_delNurb(editnurb, nu);
1957                                         BKE_nurb_free(nu); nu = NULL;
1958                                 }
1959                         }
1960                 }
1961
1962                 /* Never allow the order to exceed the number of points
1963                  * - note, this is ok but changes unselected nurbs, disable for now */
1964 #if 0
1965                 if ((nu != NULL) && (nu->type == CU_NURBS)) {
1966                         clamp_nurb_order_u(nu);
1967                 }
1968 #endif
1969                 nu = next;
1970                 nuindex++;
1971         }
1972         /* 2nd loop, delete small pieces: just for curves */
1973         nu = nubase->first;
1974         while (nu) {
1975                 next = nu->next;
1976                 type = 0;
1977                 if (nu->type == CU_BEZIER) {
1978                         int delta = 0;
1979                         bezt = nu->bezt;
1980                         for (a = 0; a < nu->pntsu; a++) {
1981                                 if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
1982                                         memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple));
1983                                         keyIndex_delBezt(editnurb, bezt + delta);
1984                                         keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1);
1985                                         nu->pntsu--;
1986                                         a--;
1987                                         type = 1;
1988                                         delta++;
1989                                 }
1990                                 else {
1991                                         bezt++;
1992                                 }
1993                         }
1994                         if (type) {
1995                                 bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb");
1996                                 memcpy(bezt1, nu->bezt, (nu->pntsu) * sizeof(BezTriple));
1997                                 keyIndex_updateBezt(editnurb, nu->bezt, bezt1, nu->pntsu);
1998                                 MEM_freeN(nu->bezt);
1999                                 nu->bezt = bezt1;
2000                                 BKE_nurb_handles_calc(nu);
2001                         }
2002                 }
2003                 else if (nu->pntsv == 1) {
2004                         int delta = 0;
2005                         bp = nu->bp;
2006
2007                         for (a = 0; a < nu->pntsu; a++) {
2008                                 if (bp->f1 & SELECT) {
2009                                         memmove(bp, bp + 1, (nu->pntsu - a - 1) * sizeof(BPoint));
2010                                         keyIndex_delBP(editnurb, bp + delta);
2011                                         keyIndex_updateBP(editnurb, bp + 1, bp, nu->pntsu - a - 1);
2012                                         nu->pntsu--;
2013                                         a--;
2014                                         type = 1;
2015                                         delta++;
2016                                 }
2017                                 else {
2018                                         bp++;
2019                                 }
2020                         }
2021                         if (type) {
2022                                 bp1 = (BPoint *)MEM_mallocN(nu->pntsu * sizeof(BPoint), "delNurb2");
2023                                 memcpy(bp1, nu->bp, (nu->pntsu) * sizeof(BPoint));
2024                                 keyIndex_updateBP(editnurb, nu->bp, bp1, nu->pntsu);
2025                                 MEM_freeN(nu->bp);
2026                                 nu->bp = bp1;
2027
2028                                 /* Never allow the order to exceed the number of points
2029                                  * - note, this is ok but changes unselected nurbs, disable for now */
2030 #if 0
2031                                 if (nu->type == CU_NURBS) {
2032                                         clamp_nurb_order_u(nu);
2033                                 }
2034 #endif
2035                         }
2036                         BKE_nurb_order_clamp_u(nu);
2037                         BKE_nurb_knot_calc_u(nu);
2038                 }
2039                 nu = next;
2040         }
2041 }
2042
2043 /* only for OB_SURF */
2044 bool ed_editnurb_extrude_flag(EditNurb *editnurb, short flag)
2045 {
2046         Nurb *nu;
2047         BPoint *bp, *bpn, *newbp;
2048         int a, u, v, len;
2049         bool ok = false;
2050
2051         nu = editnurb->nurbs.first;
2052         while (nu) {
2053
2054                 if (nu->pntsv == 1) {
2055                         bp = nu->bp;
2056                         a = nu->pntsu;
2057                         while (a) {
2058                                 if (bp->f1 & flag) {
2059                                         /* pass */
2060                                 }
2061                                 else {
2062                                         break;
2063                                 }
2064                                 bp++;
2065                                 a--;
2066                         }
2067                         if (a == 0) {
2068                                 ok = true;
2069                                 newbp = (BPoint *)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
2070                                 ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
2071                                 bp = newbp + nu->pntsu;
2072                                 ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu);
2073                                 MEM_freeN(nu->bp);
2074                                 nu->bp = newbp;
2075                                 a = nu->pntsu;
2076                                 while (a--) {
2077                                         select_bpoint(bp, SELECT, flag, HIDDEN);
2078                                         select_bpoint(newbp, DESELECT, flag, HIDDEN);
2079                                         bp++; 
2080                                         newbp++;
2081                                 }
2082
2083                                 nu->pntsv = 2;
2084                                 nu->orderv = 2;
2085                                 BKE_nurb_knot_calc_v(nu);
2086                         }
2087                 }
2088                 else {
2089                         /* which row or column is selected */
2090
2091                         if (isNurbselUV(nu, &u, &v, flag)) {
2092
2093                                 /* deselect all */
2094                                 bp = nu->bp;
2095                                 a = nu->pntsu * nu->pntsv;
2096                                 while (a--) {
2097                                         select_bpoint(bp, DESELECT, flag, HIDDEN);
2098                                         bp++;
2099                                 }
2100
2101                                 if (u == 0 || u == nu->pntsv - 1) {      /* row in u-direction selected */
2102                                         ok = true;
2103                                         newbp = (BPoint *)MEM_mallocN(nu->pntsu * (nu->pntsv + 1) *
2104                                                                       sizeof(BPoint), "extrudeNurb1");
2105                                         if (u == 0) {
2106                                                 len = nu->pntsv * nu->pntsu;
2107                                                 ED_curve_bpcpy(editnurb, newbp + nu->pntsu, nu->bp, len);
2108                                                 ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
2109                                                 bp = newbp;
2110                                         }
2111                                         else {
2112                                                 len = nu->pntsv * nu->pntsu;
2113                                                 ED_curve_bpcpy(editnurb, newbp, nu->bp, len);
2114                                                 ED_curve_bpcpy(editnurb, newbp + len, &nu->bp[len - nu->pntsu], nu->pntsu);
2115                                                 bp = newbp + len;
2116                                         }
2117
2118                                         a = nu->pntsu;
2119                                         while (a--) {
2120                                                 select_bpoint(bp, SELECT, flag, HIDDEN);
2121                                                 bp++;
2122                                         }
2123
2124                                         MEM_freeN(nu->bp);
2125                                         nu->bp = newbp;
2126                                         nu->pntsv++;
2127                                         BKE_nurb_knot_calc_v(nu);
2128                                 }
2129                                 else if (v == 0 || v == nu->pntsu - 1) {     /* column in v-direction selected */
2130                                         ok = true;
2131                                         bpn = newbp = (BPoint *)MEM_mallocN((nu->pntsu + 1) * nu->pntsv * sizeof(BPoint), "extrudeNurb1");
2132                                         bp = nu->bp;
2133
2134                                         for (a = 0; a < nu->pntsv; a++) {
2135                                                 if (v == 0) {
2136                                                         *bpn = *bp;
2137                                                         bpn->f1 |= flag;
2138                                                         bpn++;
2139                                                 }
2140                                                 ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu);
2141                                                 bp += nu->pntsu;
2142                                                 bpn += nu->pntsu;
2143                                                 if (v == nu->pntsu - 1) {
2144                                                         *bpn = *(bp - 1);
2145                                                         bpn->f1 |= flag;
2146                                                         bpn++;
2147                                                 }
2148                                         }
2149
2150                                         MEM_freeN(nu->bp);
2151                                         nu->bp = newbp;
2152                                         nu->pntsu++;
2153                                         BKE_nurb_knot_calc_u(nu);
2154                                 }
2155                         }
2156                 }
2157                 nu = nu->next;
2158         }
2159
2160         return ok;
2161 }
2162
2163 static void adduplicateflagNurb(Object *obedit, ListBase *newnurb,
2164                                 const short flag, const bool split)
2165 {
2166         ListBase *editnurb = object_editcurve_get(obedit);
2167         Nurb *nu = editnurb->last, *newnu;
2168         BezTriple *bezt, *bezt1;
2169         BPoint *bp, *bp1, *bp2, *bp3;
2170         Curve *cu = (Curve *)obedit->data;
2171         int a, b, c, starta, enda, diffa, cyclicu, cyclicv, newu, newv;
2172         char *usel;
2173
2174         while (nu) {
2175                 cyclicu = cyclicv = 0;
2176                 if (nu->type == CU_BEZIER) {
2177                         for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
2178                                 enda = -1;
2179                                 starta = a;
2180                                 while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) {
2181                                         if (!split) select_beztriple(bezt, DESELECT, flag, HIDDEN);
2182                                         enda = a;
2183                                         if (a >= nu->pntsu - 1) break;
2184                                         a++;
2185                                         bezt++;
2186                                 }
2187                                 if (enda >= starta) {
2188                                         newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
2189
2190                                         if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
2191                                                 cyclicu = newu;
2192                                         }
2193                                         else {
2194                                                 if (enda == nu->pntsu - 1) newu += cyclicu;
2195
2196                                                 newnu = BKE_nurb_copy(nu, newu, 1);
2197                                                 BLI_addtail(newnurb, newnu);
2198                                                 memcpy(newnu->bezt, &nu->bezt[starta], diffa * sizeof(BezTriple));
2199                                                 if (newu != diffa) {
2200                                                         memcpy(&newnu->bezt[diffa], nu->bezt, cyclicu * sizeof(BezTriple));
2201                                                         cyclicu = 0;
2202                                                 }
2203
2204                                                 if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
2205
2206                                                 for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
2207                                                         select_beztriple(bezt1, SELECT, flag, HIDDEN);
2208                                                 }
2209                                         }
2210                                 }
2211                         }
2212
2213                         if (cyclicu != 0) {
2214                                 newnu = BKE_nurb_copy(nu, cyclicu, 1);
2215                                 BLI_addtail(newnurb, newnu);
2216                                 memcpy(newnu->bezt, nu->bezt, cyclicu * sizeof(BezTriple));
2217                                 newnu->flagu &= ~CU_NURB_CYCLIC;
2218
2219                                 for (b = 0, bezt1 = newnu->bezt; b < newnu->pntsu; b++, bezt1++) {
2220                                         select_beztriple(bezt1, SELECT, flag, HIDDEN);
2221                                 }
2222                         }
2223                 }
2224                 else if (nu->pntsv == 1) {    /* because UV Nurb has a different method for dupli */
2225                         for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) {
2226                                 enda = -1;
2227                                 starta = a;
2228                                 while (bp->f1 & flag) {
2229                                         if (!split) select_bpoint(bp, DESELECT, flag, HIDDEN);
2230                                         enda = a;
2231                                         if (a >= nu->pntsu - 1) break;
2232                                         a++;
2233                                         bp++;
2234                                 }
2235                                 if (enda >= starta) {
2236                                         newu = diffa = enda - starta + 1; /* set newu and diffa, may use both */
2237
2238                                         if (starta == 0 && newu != nu->pntsu && (nu->flagu & CU_NURB_CYCLIC)) {
2239                                                 cyclicu = newu;
2240                                         }
2241                                         else {
2242                                                 if (enda == nu->pntsu - 1) newu += cyclicu;
2243
2244                                                 newnu = BKE_nurb_copy(nu, newu, 1);
2245                                                 BLI_addtail(newnurb, newnu);
2246                                                 memcpy(newnu->bp, &nu->bp[starta], diffa * sizeof(BPoint));
2247                                                 if (newu != diffa) {
2248                                                         memcpy(&newnu->bp[diffa], nu->bp, cyclicu * sizeof(BPoint));
2249                                                         cyclicu = 0;
2250                                                 }
2251
2252                                                 if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
2253
2254                                                 for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
2255                                                         select_bpoint(bp1, SELECT, flag, HIDDEN);
2256                                                 }
2257                                         }
2258                                 }
2259                         }
2260
2261                         if (cyclicu != 0) {
2262                                 newnu = BKE_nurb_copy(nu, cyclicu, 1);
2263                                 BLI_addtail(newnurb, newnu);
2264                                 memcpy(newnu->bp, nu->bp, cyclicu * sizeof(BPoint));
2265                                 newnu->flagu &= ~CU_NURB_CYCLIC;
2266
2267                                 for (b = 0, bp1 = newnu->bp; b < newnu->pntsu; b++, bp1++) {
2268                                         select_bpoint(bp1, SELECT, flag, HIDDEN);
2269                                 }
2270                         }
2271                 }
2272                 else {
2273                         if (isNurbsel(nu)) {
2274                                 /* a rectangular area in nurb has to be selected and if splitting must be in U or V direction */
2275                                 usel = MEM_callocN(nu->pntsu, "adduplicateN3");
2276                                 bp = nu->bp;
2277                                 for (a = 0; a < nu->pntsv; a++) {
2278                                         for (b = 0; b < nu->pntsu; b++, bp++) {
2279                                                 if (bp->f1 & flag) usel[b]++;
2280                                         }
2281                                 }
2282                                 newu = 0;
2283                                 newv = 0;
2284                                 for (a = 0; a < nu->pntsu; a++) {
2285                                         if (usel[a]) {
2286                                                 if (newv == 0 || usel[a] == newv) {
2287                                                         newv = usel[a];
2288                                                         newu++;
2289                                                 }
2290                                                 else {
2291                                                         newv = 0;
2292                                                         break;
2293                                                 }
2294                                         }
2295                                 }
2296                                 MEM_freeN(usel);
2297
2298                                 if ((newu == 0 || newv == 0) ||
2299                                     (split && !isNurbselU(nu, &newv, SELECT) && !isNurbselV(nu, &newu, SELECT)))
2300                                 {
2301                                         if (G.debug & G_DEBUG)
2302                                                 printf("Can't duplicate Nurb\n");
2303                                 }
2304                                 else {
2305                                         for (a = 0, bp1 = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp1++) {
2306                                                 newv = newu = 0;
2307
2308                                                 if ((bp1->f1 & flag) && !(bp1->f1 & SURF_SEEN)) {
2309                                                         /* point selected, now loop over points in U and V directions */
2310                                                         for (b = a % nu->pntsu, bp2 = bp1; b < nu->pntsu; b++, bp2++) {
2311                                                                 if (bp2->f1 & flag) {
2312                                                                         newu++;
2313                                                                         for (c = a / nu->pntsu, bp3 = bp2; c < nu->pntsv; c++, bp3 += nu->pntsu) {
2314                                                                                 if (bp3->f1 & flag) {
2315                                                                                         bp3->f1 |= SURF_SEEN; /* flag as seen so skipped on future iterations */
2316                                                                                         if (newu == 1) newv++;
2317                                                                                 }
2318                                                                                 else {
2319                                                                                         break;
2320                                                                                 }
2321                                                                         }
2322                                                                 }
2323                                                                 else {
2324                                                                         break;
2325                                                                 }
2326                                                         }
2327                                                 }
2328
2329                                                 if ((newu + newv) > 2) {
2330                                                         /* ignore single points */
2331                                                         if (a == 0) {
2332                                                                 /* check if need to save cyclic selection and continue if so */
2333                                                                 if (newu == nu->pntsu && (nu->flagv & CU_NURB_CYCLIC)) cyclicv = newv;
2334                                                                 if (newv == nu->pntsv && (nu->flagu & CU_NURB_CYCLIC)) cyclicu = newu;
2335                                                                 if (cyclicu != 0 || cyclicv != 0) continue;
2336                                                         }
2337
2338                                                         if (a + newu == nu->pntsu && cyclicu != 0) {
2339                                                                 /* cyclic in U direction */
2340                                                                 newnu = BKE_nurb_copy(nu, newu + cyclicu, newv);
2341                                                                 for (b = 0; b < newv; b++) {
2342                                                                         memcpy(&newnu->bp[b * newnu->pntsu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
2343                                                                         memcpy(&newnu->bp[b * newnu->pntsu + newu], &nu->bp[b * nu->pntsu], cyclicu * sizeof(BPoint));
2344                                                                 }
2345                                                                 cyclicu = cyclicv = 0;
2346                                                         }
2347                                                         else if ((a / nu->pntsu) + newv == nu->pntsv && cyclicv != 0) {
2348                                                                 /* cyclic in V direction */
2349                                                                 newnu = BKE_nurb_copy(nu, newu, newv + cyclicv);
2350                                                                 memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint));
2351                                                                 memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint));
2352                                                                 cyclicu = cyclicv = 0;
2353                                                         }
2354                                                         else {
2355                                                                 newnu = BKE_nurb_copy(nu, newu, newv);
2356                                                                 for (b = 0; b < newv; b++) {
2357                                                                         memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu + a], newu * sizeof(BPoint));
2358                                                                 }
2359                                                         }
2360                                                         BLI_addtail(newnurb, newnu);
2361
2362                                                         if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
2363                                                         if (newv != nu->pntsv) newnu->flagv &= ~CU_NURB_CYCLIC;
2364                                                 }
2365                                         }
2366
2367                                         if (cyclicu != 0 || cyclicv != 0) {
2368                                                 /* copy start of a cyclic surface, or copying all selected points */
2369                                                 newu = cyclicu == 0 ? nu->pntsu : cyclicu;
2370                                                 newv = cyclicv == 0 ? nu->pntsv : cyclicv;
2371
2372                                                 newnu = BKE_nurb_copy(nu, newu, newv);
2373                                                 for (b = 0; b < newv; b++) {
2374                                                         memcpy(&newnu->bp[b * newu], &nu->bp[b * nu->pntsu], newu * sizeof(BPoint));
2375                                                 }
2376                                                 BLI_addtail(newnurb, newnu);
2377
2378                                                 if (newu != nu->pntsu) newnu->flagu &= ~CU_NURB_CYCLIC;
2379                                                 if (newv != nu->pntsv) newnu->flagv &= ~CU_NURB_CYCLIC;
2380                                         }
2381
2382                                         for (b = 0, bp1 = nu->bp; b < nu->pntsu * nu->pntsv; b++, bp1++) {
2383                                                 bp1->f1 &= ~SURF_SEEN;
2384                                                 if (!split) select_bpoint(bp1, DESELECT, flag, HIDDEN);
2385                                         }
2386                                 }
2387                         }
2388                 }
2389                 nu = nu->prev;
2390         }
2391
2392         if (BLI_listbase_is_empty(newnurb) == false) {
2393                 cu->actnu = cu->actvert = CU_ACT_NONE;
2394
2395                 for (nu = newnurb->first; nu; nu = nu->next) {
2396                         if (nu->type == CU_BEZIER) {
2397                                 if (split) {
2398                                         /* recalc first and last */
2399                                         BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]);
2400                                         BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]);
2401                                 }
2402                         }
2403                         else {
2404                                 /* knots done after duplicate as pntsu may change */
2405                                 nu->knotsu = nu->knotsv = NULL;
2406                                 BKE_nurb_order_clamp_u(nu);
2407                                 BKE_nurb_knot_calc_u(nu);
2408
2409                                 if (obedit->type == OB_SURF) {
2410                                         for (a = 0, bp = nu->bp; a < nu->pntsu * nu->pntsv; a++, bp++) {
2411                                                 bp->f1 &= ~SURF_SEEN;
2412                                         }
2413
2414                                         BKE_nurb_order_clamp_v(nu);
2415                                         BKE_nurb_knot_calc_v(nu);
2416                                 }
2417                         }
2418                 }
2419         }
2420 }
2421
2422 /**************** switch direction operator ***************/
2423
2424 static int switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
2425 {
2426         Object *obedit = CTX_data_edit_object(C);
2427         Curve *cu = (Curve *)obedit->data;
2428         EditNurb *editnurb = cu->editnurb;
2429         Nurb *nu;
2430         int i;
2431
2432         for (nu = editnurb->nurbs.first, i = 0; nu; nu = nu->next, i++) {
2433                 if (isNurbsel(nu)) {
2434                         BKE_nurb_direction_switch(nu);
2435                         keyData_switchDirectionNurb(cu, nu);
2436                         if ((i == cu->actnu) && (cu->actvert != CU_ACT_NONE)) {
2437                                 cu->actvert = (nu->pntsu - 1) - cu->actvert;
2438                         }
2439                 }
2440         }
2441
2442         if (ED_curve_updateAnimPaths(obedit->data))
2443                 WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit);
2444
2445         DAG_id_tag_update(obedit->data, 0);
2446         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2447
2448         return OPERATOR_FINISHED;
2449 }
2450
2451 void CURVE_OT_switch_direction(wmOperatorType *ot)
2452 {
2453         /* identifiers */
2454         ot->name = "Switch Direction";
2455         ot->description = "Switch direction of selected splines";
2456         ot->idname = "CURVE_OT_switch_direction";
2457         
2458         /* api callbacks */
2459         ot->exec = switch_direction_exec;
2460         ot->poll = ED_operator_editsurfcurve;
2461
2462         /* flags */
2463         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2464 }
2465
2466 /****************** set weight operator *******************/
2467
2468 static int set_goal_weight_exec(bContext *C, wmOperator *op)
2469 {
2470         Object *obedit = CTX_data_edit_object(C);
2471         ListBase *editnurb = object_editcurve_get(obedit);
2472         Nurb *nu;
2473         BezTriple *bezt;
2474         BPoint *bp;
2475         float weight = RNA_float_get(op->ptr, "weight");
2476         int a;
2477                                 
2478         for (nu = editnurb->first; nu; nu = nu->next) {
2479                 if (nu->bezt) {
2480                         for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
2481                                 if (bezt->f2 & SELECT)
2482                                         bezt->weight = weight;
2483                         }
2484                 }
2485                 else if (nu->bp) {
2486                         for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
2487                                 if (bp->f1 & SELECT)
2488                                         bp->weight = weight;
2489                         }
2490                 }
2491         }
2492
2493         DAG_id_tag_update(obedit->data, 0);
2494         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2495
2496         return OPERATOR_FINISHED;
2497 }
2498
2499 void CURVE_OT_spline_weight_set(wmOperatorType *ot)
2500 {
2501         /* identifiers */
2502         ot->name = "Set Goal Weight";
2503         ot->description = "Set softbody goal weight for selected points";
2504         ot->idname = "CURVE_OT_spline_weight_set";
2505         
2506         /* api callbacks */
2507         ot->exec = set_goal_weight_exec;
2508         ot->invoke = WM_operator_props_popup;
2509         ot->poll = ED_operator_editsurfcurve;
2510
2511         /* flags */
2512         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2513
2514         /* properties */
2515         RNA_def_float_factor(ot->srna, "weight", 1.0f, 0.0f, 1.0f, "Weight", "", 0.0f, 1.0f);
2516 }
2517
2518 /******************* set radius operator ******************/
2519
2520 static int set_radius_exec(bContext *C, wmOperator *op)
2521 {
2522         Object *obedit = CTX_data_edit_object(C);
2523         ListBase *editnurb = object_editcurve_get(obedit);
2524         Nurb *nu;
2525         BezTriple *bezt;
2526         BPoint *bp;
2527         float radius = RNA_float_get(op->ptr, "radius");
2528         int a;
2529         
2530         for (nu = editnurb->first; nu; nu = nu->next) {
2531                 if (nu->bezt) {
2532                         for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++) {
2533                                 if (bezt->f2 & SELECT)
2534                                         bezt->radius = radius;
2535                         }
2536                 }
2537                 else if (nu->bp) {
2538                         for (bp = nu->bp, a = 0; a < nu->pntsu * nu->pntsv; a++, bp++) {
2539                                 if (bp->f1 & SELECT)
2540                                         bp->radius = radius;
2541                         }
2542                 }
2543         }
2544
2545         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2546         DAG_id_tag_update(obedit->data, 0);
2547
2548         return OPERATOR_FINISHED;
2549 }
2550
2551 void CURVE_OT_radius_set(wmOperatorType *ot)
2552 {
2553         /* identifiers */
2554         ot->name = "Set Curve Radius";
2555         ot->description = "Set per-point radius which is used for bevel tapering";
2556         ot->idname = "CURVE_OT_radius_set";
2557         
2558         /* api callbacks */
2559         ot->exec = set_radius_exec;
2560         ot->invoke = WM_operator_props_popup;
2561         ot->poll = ED_operator_editsurfcurve;
2562
2563         /* flags */
2564         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2565
2566         /* properties */
2567         RNA_def_float(ot->srna, "radius", 1.0f, 0.0f, FLT_MAX, "Radius", "", 0.0001f, 10.0f);
2568 }
2569
2570 /********************* smooth operator ********************/
2571
2572 static void smooth_single_bezt(
2573         BezTriple *bezt,
2574         const BezTriple *bezt_orig_prev, const BezTriple *bezt_orig_next,
2575         float factor)
2576 {
2577         int i;
2578
2579         BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f));
2580
2581         for (i = 0; i < 3; i++) {
2582                 float val_old, val_new, offset;
2583
2584                 /* get single dimension pos of the mid handle */
2585                 val_old = bezt->vec[1][i];
2586
2587                 /* get the weights of the previous/next mid handles and calc offset */
2588                 val_new = (bezt_orig_prev->vec[1][i] * 0.5f) + (bezt_orig_next->vec[1][i] * 0.5f);
2589                 offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old;
2590
2591                 /* offset midpoint and 2 handles */
2592                 bezt->vec[1][i] += offset;
2593                 bezt->vec[0][i] += offset;
2594                 bezt->vec[2][i] += offset;
2595         }
2596 }
2597
2598 /**
2599  * Same as smooth_single_bezt(), keep in sync
2600  */
2601 static void smooth_single_bp(
2602         BPoint *bp,
2603         const BPoint *bp_orig_prev, const BPoint *bp_orig_next,
2604         float factor)
2605 {
2606         int i;
2607
2608         BLI_assert(IN_RANGE_INCL(factor, 0.0f, 1.0f));
2609
2610         for (i = 0; i < 3; i++) {
2611                 float val_old, val_new, offset;
2612
2613                 val_old = bp->vec[i];
2614                 val_new = (bp_orig_prev->vec[i] * 0.5f) + (bp_orig_next->vec[i] * 0.5f);
2615                 offset = (val_old * (1.0f - factor)) + (val_new * factor) - val_old;
2616
2617                 bp->vec[i] += offset;
2618         }
2619 }
2620
2621 static int smooth_exec(bContext *C, wmOperator *UNUSED(op))
2622 {
2623         const float factor = 1.0f / 6.0f;
2624         Object *obedit = CTX_data_edit_object(C);
2625         ListBase *editnurb = object_editcurve_get(obedit);
2626         Nurb *nu;
2627
2628         int a, a_end;
2629         bool changed = false;
2630
2631         for (nu = editnurb->first; nu; nu = nu->next) {
2632                 if (nu->bezt) {
2633                         /* duplicate the curve to use in weight calculation */
2634                         const BezTriple *bezt_orig = MEM_dupallocN(nu->bezt);
2635                         BezTriple *bezt;
2636                         changed = false;
2637
2638                         /* check whether its cyclic or not, and set initial & final conditions */
2639                         if (nu->flagu & CU_NURB_CYCLIC) {
2640                                 a = 0;
2641                                 a_end = nu->pntsu;
2642                         }
2643                         else {
2644                                 a = 1;
2645                                 a_end = nu->pntsu - 1;
2646                         }
2647
2648                         /* for all the curve points */
2649                         for (; a < a_end; a++) {
2650                                 /* respect selection */
2651                                 bezt = &nu->bezt[a];
2652                                 if (bezt->f2 & SELECT) {
2653                                         const BezTriple *bezt_orig_prev, *bezt_orig_next;
2654
2655                                         bezt_orig_prev = &bezt_orig[mod_i(a - 1, nu->pntsu)];
2656                                         bezt_orig_next = &bezt_orig[mod_i(a + 1, nu->pntsu)];
2657
2658                                         smooth_single_bezt(bezt, bezt_orig_prev, bezt_orig_next, factor);
2659
2660                                         changed = true;
2661                                 }
2662                         }
2663                         MEM_freeN((void *)bezt_orig);
2664                         if (changed) {
2665                                 BKE_nurb_handles_calc(nu);
2666                         }
2667                 }
2668                 else if (nu->bp) {
2669                         /* Same as above, keep these the same! */
2670                         const BPoint *bp_orig = MEM_dupallocN(nu->bp);
2671                         BPoint *bp;
2672
2673                         if (nu->flagu & CU_NURB_CYCLIC) {
2674                                 a = 0;
2675                                 a_end = nu->pntsu;
2676                         }
2677                         else {
2678                                 a = 1;
2679                                 a_end = nu->pntsu - 1;
2680                         }
2681
2682                         for (; a < a_end; a++) {
2683                                 bp = &nu->bp[a];
2684                                 if (bp->f1 & SELECT) {
2685                                         const BPoint *bp_orig_prev, *bp_orig_next;
2686
2687                                         bp_orig_prev = &bp_orig[mod_i(a - 1, nu->pntsu)];
2688                                         bp_orig_next = &bp_orig[mod_i(a + 1, nu->pntsu)];
2689
2690                                         smooth_single_bp(bp, bp_orig_prev, bp_orig_next, factor);
2691                                 }
2692                         }
2693                         MEM_freeN((void *)bp_orig);
2694                 }
2695         }
2696
2697         WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
2698         DAG_id_tag_update(obedit->data, 0);
2699
2700         return OPERATOR_FINISHED;
2701 }
2702
2703 void CURVE_OT_smooth(wmOperatorType *ot)
2704 {
2705         /* identifiers */
2706         ot->name = "Smooth";
2707         ot->description = "Flatten angles of selected points";
2708         ot->idname = "CURVE_OT_smooth";
2709         
2710         /* api callbacks */
2711         ot->exec = smooth_exec;
2712         ot->poll = ED_operator_editsurfcurve;
2713
2714         /* flags */
2715         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2716 }
2717
2718 /* -------------------------------------------------------------------- */
2719 /* Smooth radius/weight/tilt
2720  *
2721  * TODO: make smoothing distance based
2722  * TODO: support cyclic curves
2723  */
2724
2725 static void curve_smooth_value(ListBase *editnurb,
2726                                const int bezt_offsetof, const int bp_offset)
2727 {
2728         Nurb *nu;
2729         BezTriple *bezt;
2730         BPoint *bp;
2731         int a;
2732
2733         /* use for smoothing */
2734         int last_sel;
2735         int start_sel, end_sel; /* selection indices, inclusive */
2736         float start_rad, end_rad, fac, range;
2737
2738         for (nu = editnurb->first; nu; nu = nu->next) {
2739                 if (nu->bezt) {
2740 #define BEZT_VALUE(bezt) (*((float *)((char *)bezt + bezt_offsetof)))
2741
2742                         for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
2743                                 /* loop over selection segments of a curve, smooth each */
2744
2745                                 /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */
2746                                 start_sel = -1;
2747                                 for (bezt = &nu->bezt[last_sel], a = last_sel; a < nu->pntsu; a++, bezt++) {
2748                                         if (bezt->f2 & SELECT) {
2749                                                 start_sel = a;
2750                                                 break;
2751                                         }
2752                                 }
2753                                 /* in case there are no other selected verts */
2754                                 end_sel = start_sel;
2755                                 for (bezt = &nu->bezt[start_sel + 1], a = start_sel + 1; a < nu->pntsu; a++, bezt++) {
2756                                         if ((bezt->f2 & SELECT) == 0) {
2757                                                 break;
2758                                         }
2759                                         end_sel = a;
2760                                 }
2761
2762                                 if (start_sel == -1) {
2763                                         last_sel = nu->pntsu; /* next... */
2764                                 }
2765                                 else {
2766                                         last_sel = end_sel; /* before we modify it */
2767
2768                                         /* now blend between start and end sel */
2769                                         start_rad = end_rad = FLT_MAX;
2770
2771                                         if (start_sel == end_sel) {
2772                                                 /* simple, only 1 point selected */
2773                                                 if (start_sel > 0)                         start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]);
2774                                                 if (end_sel != -1 && end_sel < nu->pntsu)  end_rad   = BEZT_VALUE(&nu->bezt[start_sel + 1]);
2775
2776                                                 if      (start_rad != FLT_MAX && end_rad >= FLT_MAX) BEZT_VALUE(&nu->bezt[start_sel]) = (start_rad + end_rad) / 2.0f;
2777                                                 else if (start_rad != FLT_MAX)                       BEZT_VALUE(&nu->bezt[start_sel]) = start_rad;
2778                                                 else if (end_rad   != FLT_MAX)                       BEZT_VALUE(&nu->bezt[start_sel]) = end_rad;
2779                                         }
2780                                         else {
2781                                                 /* if endpoints selected, then use them */
2782                                                 if (start_sel == 0) {
2783                                                         start_rad = BEZT_VALUE(&nu->bezt[start_sel]);
2784                                                         start_sel++; /* we don't want to edit the selected endpoint */
2785                                                 }
2786                                                 else {
2787                                                         start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]);
2788                                                 }
2789                                                 if (end_sel == nu->pntsu - 1) {
2790                                                         end_rad = BEZT_VALUE(&nu->bezt[end_sel]);
2791                                                         end_sel--; /* we don't want to edit the selected endpoint */
2792                                                 }
2793                                                 else {
2794                                                         end_rad = BEZT_VALUE(&nu->bezt[end_sel + 1]);
2795                                                 }
2796
2797                                                 /* Now Blend between the points */
2798                                                 range = (float)(end_sel - start_sel) + 2.0f;
2799                                                 for (bezt = &nu->bezt[start_sel], a = start_sel; a <= end_sel; a++, bezt++) {
2800                                                         fac = (float)(1 + a - start_sel) / range;
2801                                                         BEZT_VALUE(bezt) = start_rad * (1.0f - fac) + end_rad * fac;
2802                                                 }
2803                                         }
2804                                 }
2805                         }
2806 #undef BEZT_VALUE
2807                 }
2808                 else if (nu->bp) {
2809 #define BP_VALUE(bp) (*((float *)((char *)bp + bp_offset)))
2810
2811                         /* Same as above, keep these the same! */
2812                         for (last_sel = 0; last_sel < nu->pntsu; last_sel++) {
2813                                 /* loop over selection segments of a curve, smooth each */
2814
2815                                 /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */
2816                                 start_sel = -1;
2817                                 for (bp = &nu->bp[last_sel], a = last_sel; a < nu->pntsu; a++, bp++) {
2818                                         if (bp->f1 & SELECT) {
2819                                                 start_sel = a;
2820                        &nb