4ac599a024343f5fabd7fa165b2e48eebb8aeaad
[blender-staging.git] / source / blender / editors / armature / editarmature_sketch.c
1 /**
2  * $Id: $
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 #include <string.h>
24 #include <math.h>
25 #include <float.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "DNA_listBase.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_screen_types.h"
32 #include "DNA_view3d_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_armature_types.h"
36 #include "DNA_userdef_types.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_arithb.h"
40 #include "BLI_graph.h"
41 #include "BLI_ghash.h"
42
43 #include "BKE_utildefines.h"
44 #include "BKE_global.h"
45 #include "BKE_DerivedMesh.h"
46 #include "BKE_object.h"
47 #include "BKE_anim.h"
48 #include "BKE_context.h"
49
50 #include "ED_view3d.h"
51
52 #include "BIF_gl.h"
53 #include "UI_resources.h"
54 //#include "BIF_screen.h"
55 //#include "BIF_space.h"
56 //#include "BIF_mywindow.h"
57 #include "ED_armature.h"
58 #include "armature_intern.h"
59 //#include "BIF_sketch.h"
60 #include "BIF_retarget.h"
61 #include "BIF_generate.h"
62 //#include "BIF_interface.h"
63
64 #include "BIF_transform.h"
65
66 #include "WM_types.h"
67
68 //#include "blendef.h"
69 //#include "mydevice.h"
70 #include "reeb.h"
71
72 typedef enum SK_PType
73 {
74         PT_CONTINUOUS,
75         PT_EXACT,
76 } SK_PType;
77
78 typedef enum SK_PMode
79 {
80         PT_SNAP,
81         PT_PROJECT,
82 } SK_PMode;
83
84 typedef struct SK_Point
85 {
86         float p[3];
87         float no[3];
88         SK_PType type;
89         SK_PMode mode;
90 } SK_Point;
91
92 typedef struct SK_Stroke
93 {
94         struct SK_Stroke *next, *prev;
95
96         SK_Point *points;
97         int nb_points;
98         int buf_size;
99         int selected;
100 } SK_Stroke;
101
102 #define SK_OVERDRAW_LIMIT       5
103
104 typedef struct SK_Overdraw
105 {
106         SK_Stroke *target;
107         int     start, end;
108         int count;
109 } SK_Overdraw;
110
111 #define SK_Stroke_BUFFER_INIT_SIZE 20
112
113 typedef struct SK_DrawData
114 {
115         short mval[2];
116         short previous_mval[2];
117         SK_PType type;
118 } SK_DrawData;
119
120 typedef struct SK_Intersection
121 {
122         struct SK_Intersection *next, *prev;
123         SK_Stroke *stroke;
124         int                     before;
125         int                     after;
126         int                     gesture_index;
127         float           p[3];
128         float           lambda; /* used for sorting intersection points */
129 } SK_Intersection;
130
131 typedef struct SK_Sketch
132 {
133         ListBase        strokes;
134         SK_Stroke       *active_stroke;
135         SK_Stroke       *gesture;
136         SK_Point        next_point;
137         SK_Overdraw over;
138 } SK_Sketch;
139
140 typedef struct SK_StrokeIterator {
141         HeadFct         head;
142         TailFct         tail;
143         PeekFct         peek;
144         NextFct         next;
145         NextNFct        nextN;
146         PreviousFct     previous;
147         StoppedFct      stopped;
148         
149         float *p, *no;
150         
151         int length;
152         int index;
153         /*********************************/
154         SK_Stroke *stroke;
155         int start;
156         int end;
157         int stride;
158 } SK_StrokeIterator;
159
160 typedef struct SK_Gesture {
161         SK_Stroke       *stk;
162         SK_Stroke       *segments;
163
164         ListBase        intersections;
165         ListBase        self_intersections;
166
167         int                     nb_self_intersections;
168         int                     nb_intersections;
169         int                     nb_segments;
170 } SK_Gesture;
171
172 typedef int  (*GestureDetectFct)(bContext*, SK_Gesture*, SK_Sketch *);
173 typedef void (*GestureApplyFct)(bContext*, SK_Gesture*, SK_Sketch *);
174
175 typedef struct SK_GestureAction {
176         char name[64];
177         GestureDetectFct        detect;
178         GestureApplyFct         apply;
179 } SK_GestureAction;
180
181 SK_Sketch *GLOBAL_sketch = NULL;
182 SK_Point boneSnap;
183 int    LAST_SNAP_POINT_VALID = 0;
184 float  LAST_SNAP_POINT[3];
185
186 /******************** PROTOTYPES ******************************/
187
188 void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
189
190 void sk_deleteSelectedStrokes(SK_Sketch *sketch);
191
192 void sk_freeStroke(SK_Stroke *stk);
193 void sk_freeSketch(SK_Sketch *sketch);
194
195 SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
196
197 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
198 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
199 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
200 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
201 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
202 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
203 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
204 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
205 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
206 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
207 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
208 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
209 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
210 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
211
212
213 void sk_resetOverdraw(SK_Sketch *sketch);
214 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
215
216 /******************** GESTURE ACTIONS ******************************/
217
218 SK_GestureAction GESTURE_ACTIONS[] =
219         {
220                 {"Cut", sk_detectCutGesture, sk_applyCutGesture},
221                 {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
222                 {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
223                 {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
224                 {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
225                 {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
226                 {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
227                 {"", NULL, NULL}
228         };
229
230 /******************** TEMPLATES UTILS *************************/
231
232 char  *TEMPLATES_MENU = NULL;
233 int    TEMPLATES_CURRENT = 0;
234 GHash *TEMPLATES_HASH = NULL;
235 RigGraph *TEMPLATE_RIGG = NULL;
236
237 void BIF_makeListTemplates(bContext *C)
238 {
239         Object *obedit = CTX_data_edit_object(C);
240         Scene *scene = CTX_data_scene(C);
241         Base *base;
242         int index = 0;
243
244         if (TEMPLATES_HASH != NULL)
245         {
246                 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
247         }
248         
249         TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
250         TEMPLATES_CURRENT = 0;
251
252         for ( base = FIRSTBASE; base; base = base->next )
253         {
254                 Object *ob = base->object;
255                 
256                 if (ob != obedit && ob->type == OB_ARMATURE)
257                 {
258                         index++;
259                         BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
260                         
261                         if (ob == scene->toolsettings->skgen_template)
262                         {
263                                 TEMPLATES_CURRENT = index;
264                         }
265                 }
266         }
267 }
268
269 char *BIF_listTemplates(bContext *C)
270 {
271         GHashIterator ghi;
272         char menu_header[] = "Template%t|None%x0|";
273         char *p;
274         
275         if (TEMPLATES_MENU != NULL)
276         {
277                 MEM_freeN(TEMPLATES_MENU);
278         }
279         
280         TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
281         
282         p = TEMPLATES_MENU;
283         
284         p += sprintf(TEMPLATES_MENU, "%s", menu_header);
285         
286         BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
287         
288         while (!BLI_ghashIterator_isDone(&ghi))
289         {
290                 Object *ob = BLI_ghashIterator_getValue(&ghi);
291                 int key = (int)BLI_ghashIterator_getKey(&ghi);
292                 
293                 p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
294                 
295                 BLI_ghashIterator_step(&ghi);
296         }
297         
298         return TEMPLATES_MENU;
299 }
300
301 int   BIF_currentTemplate(bContext *C)
302 {
303         Scene *scene = CTX_data_scene(C);
304         if (TEMPLATES_CURRENT == 0 && scene->toolsettings->skgen_template != NULL)
305         {
306                 GHashIterator ghi;
307                 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
308                 
309                 while (!BLI_ghashIterator_isDone(&ghi))
310                 {
311                         Object *ob = BLI_ghashIterator_getValue(&ghi);
312                         int key = (int)BLI_ghashIterator_getKey(&ghi);
313                         
314                         if (ob == scene->toolsettings->skgen_template)
315                         {
316                                 TEMPLATES_CURRENT = key;
317                                 break;
318                         }
319                         
320                         BLI_ghashIterator_step(&ghi);
321                 }
322         }
323         
324         return TEMPLATES_CURRENT;
325 }
326
327 RigGraph* sk_makeTemplateGraph(bContext *C, Object *ob)
328 {
329         Object *obedit = CTX_data_edit_object(C);
330         if (ob == obedit)
331         {
332                 return NULL;
333         }
334         
335         if (ob != NULL)
336         {
337                 if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
338                 {
339                         RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
340                         TEMPLATE_RIGG = NULL;
341                 }
342                 
343                 if (TEMPLATE_RIGG == NULL)
344                 {
345                         bArmature *arm;
346
347                         arm = ob->data;
348                         
349                         TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm);
350                 }
351         }
352         
353         return TEMPLATE_RIGG;
354 }
355
356 int BIF_nbJointsTemplate(bContext *C)
357 {
358         Scene *scene = CTX_data_scene(C);
359         RigGraph *rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
360         
361         if (rg)
362         {
363                 return RIG_nbJoints(rg);
364         }
365         else
366         {
367                 return -1; 
368         }
369 }
370
371 char * BIF_nameBoneTemplate(bContext *C)
372 {
373         Scene *scene = CTX_data_scene(C);
374         SK_Sketch *stk = GLOBAL_sketch;
375         RigGraph *rg;
376         int index = 0;
377
378         if (stk && stk->active_stroke != NULL)
379         {
380                 index = stk->active_stroke->nb_points;
381         }
382         
383         rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
384         
385         if (rg == NULL)
386         {
387                 return "";
388         }
389
390         return RIG_nameBone(rg, 0, index);
391 }
392
393 void  BIF_freeTemplates(bContext *C)
394 {
395         if (TEMPLATES_MENU != NULL)
396         {
397                 MEM_freeN(TEMPLATES_MENU);
398                 TEMPLATES_MENU = NULL;
399         }
400         
401         if (TEMPLATES_HASH != NULL)
402         {
403                 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
404                 TEMPLATES_HASH = NULL;
405         }
406         
407         if (TEMPLATE_RIGG != NULL)
408         {
409                 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
410                 TEMPLATE_RIGG = NULL;
411         }
412 }
413
414 void  BIF_setTemplate(bContext *C, int index)
415 {
416         Scene *scene = CTX_data_scene(C);
417         if (index > 0)
418         {
419                 scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
420         }
421         else
422         {
423                 scene->toolsettings->skgen_template = NULL;
424                 
425                 if (TEMPLATE_RIGG != NULL)
426                 {
427                         RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
428                 }
429                 TEMPLATE_RIGG = NULL;
430         }
431 }       
432
433 /*********************** CONVERSION ***************************/
434
435 void sk_autoname(bContext *C, ReebArc *arc)
436 {
437         Scene *scene = CTX_data_scene(C);
438         if (scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME)
439         {
440                 if (arc == NULL)
441                 {
442                         char *num = scene->toolsettings->skgen_num_string;
443                         int i = atoi(num);
444                         i++;
445                         BLI_snprintf(num, 8, "%i", i);
446                 }
447                 else
448                 {
449                         char *side = scene->toolsettings->skgen_side_string;
450                         int valid = 0;
451                         int caps = 0;
452                         
453                         if (BLI_streq(side, ""))
454                         {
455                                 valid = 1;
456                         }
457                         else if (BLI_streq(side, "R") || BLI_streq(side, "L"))
458                         {
459                                 valid = 1;
460                                 caps = 1;
461                         }
462                         else if (BLI_streq(side, "r") || BLI_streq(side, "l"))
463                         {
464                                 valid = 1;
465                                 caps = 0;
466                         }
467                         
468                         if (valid)
469                         {
470                                 if (arc->head->p[0] < 0)
471                                 {
472                                         BLI_snprintf(side, 8, caps?"R":"r");
473                                 }
474                                 else
475                                 {
476                                         BLI_snprintf(side, 8, caps?"L":"l");
477                                 }
478                         }
479                 }
480         }
481 }
482
483 ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
484 {
485         ReebNode *node;
486         
487         node = MEM_callocN(sizeof(ReebNode), "reeb node");
488         VECCOPY(node->p, pt->p);
489         Mat4MulVecfl(imat, node->p);
490         
491         VECCOPY(node->no, pt->no);
492         Mat3MulVecfl(tmat, node->no);
493         
494         return node;
495 }
496
497 ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
498 {
499         ReebArc *arc;
500         int i;
501         
502         arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
503         arc->head = sk_pointToNode(stk->points, imat, tmat);
504         arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
505         
506         arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
507         arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
508         
509         for (i = 0; i < arc->bcount; i++)
510         {
511                 VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
512                 Mat4MulVecfl(imat, arc->buckets[i].p);
513
514                 VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
515                 Mat3MulVecfl(tmat, arc->buckets[i].no);
516         }
517         
518         return arc;
519 }
520
521 void sk_retargetStroke(bContext *C, SK_Stroke *stk)
522 {
523         Scene *scene = CTX_data_scene(C);
524         Object *obedit = CTX_data_edit_object(C);
525         float imat[4][4];
526         float tmat[3][3];
527         ReebArc *arc;
528         RigGraph *rg;
529         
530         Mat4Invert(imat, obedit->obmat);
531         
532         Mat3CpyMat4(tmat, obedit->obmat);
533         Mat3Transp(tmat);
534
535         arc = sk_strokeToArc(stk, imat, tmat);
536         
537         sk_autoname(C, arc);
538         
539         rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
540
541         BIF_retargetArc(C, arc, rg);
542         
543         sk_autoname(C, NULL);
544         
545         MEM_freeN(arc->head);
546         MEM_freeN(arc->tail);
547         REEB_freeArc((BArc*)arc);
548 }
549
550 /**************************************************************/
551
552 void sk_freeSketch(SK_Sketch *sketch)
553 {
554         SK_Stroke *stk, *next;
555         
556         for (stk = sketch->strokes.first; stk; stk = next)
557         {
558                 next = stk->next;
559                 
560                 sk_freeStroke(stk);
561         }
562         
563         MEM_freeN(sketch);
564 }
565
566 SK_Sketch* sk_createSketch()
567 {
568         SK_Sketch *sketch;
569         
570         sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
571         
572         sketch->active_stroke = NULL;
573         sketch->gesture = NULL;
574
575         sketch->strokes.first = NULL;
576         sketch->strokes.last = NULL;
577         
578         return sketch;
579 }
580
581 void sk_initPoint(bContext *C, SK_Point *pt)
582 {
583         ARegion *ar = CTX_wm_region(C);
584         RegionView3D *rv3d = ar->regiondata;
585
586         VECCOPY(pt->no, rv3d->viewinv[2]);
587         Normalize(pt->no);
588         /* more init code here */
589 }
590
591 void sk_copyPoint(SK_Point *dst, SK_Point *src)
592 {
593         memcpy(dst, src, sizeof(SK_Point));
594 }
595
596 void sk_allocStrokeBuffer(SK_Stroke *stk)
597 {
598         stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
599 }
600
601 void sk_freeStroke(SK_Stroke *stk)
602 {
603         MEM_freeN(stk->points);
604         MEM_freeN(stk);
605 }
606
607 SK_Stroke* sk_createStroke()
608 {
609         SK_Stroke *stk;
610         
611         stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
612         
613         stk->selected = 0;
614         stk->nb_points = 0;
615         stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
616         
617         sk_allocStrokeBuffer(stk);
618         
619         return stk;
620 }
621
622 void sk_shrinkStrokeBuffer(SK_Stroke *stk)
623 {
624         if (stk->nb_points < stk->buf_size)
625         {
626                 SK_Point *old_points = stk->points;
627                 
628                 stk->buf_size = stk->nb_points;
629
630                 sk_allocStrokeBuffer(stk);              
631                 
632                 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
633                 
634                 MEM_freeN(old_points);
635         }
636 }
637
638 void sk_growStrokeBuffer(SK_Stroke *stk)
639 {
640         if (stk->nb_points == stk->buf_size)
641         {
642                 SK_Point *old_points = stk->points;
643                 
644                 stk->buf_size *= 2;
645                 
646                 sk_allocStrokeBuffer(stk);
647                 
648                 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
649                 
650                 MEM_freeN(old_points);
651         }
652 }
653
654 void sk_growStrokeBufferN(SK_Stroke *stk, int n)
655 {
656         if (stk->nb_points + n > stk->buf_size)
657         {
658                 SK_Point *old_points = stk->points;
659                 
660                 while (stk->nb_points + n > stk->buf_size)
661                 {
662                         stk->buf_size *= 2;
663                 }
664                 
665                 sk_allocStrokeBuffer(stk);
666                 
667                 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
668                 
669                 MEM_freeN(old_points);
670         }
671 }
672
673
674 void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
675 {
676         memcpy(stk->points + n, pt, sizeof(SK_Point));
677 }
678
679 void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
680 {
681         int size = stk->nb_points - n;
682         
683         sk_growStrokeBuffer(stk);
684         
685         memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
686         
687         memcpy(stk->points + n, pt, sizeof(SK_Point));
688         
689         stk->nb_points++;
690 }
691
692 void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
693 {
694         sk_growStrokeBuffer(stk);
695         
696         memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
697         
698         stk->nb_points++;
699 }
700
701 void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
702 {
703         int size = end - start + 1;
704         
705         sk_growStrokeBufferN(stk, len - size);
706         
707         if (len != size)
708         {
709                 int tail_size = stk->nb_points - end + 1;
710                 
711                 memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
712         }
713         
714         memcpy(stk->points + start, pts, len * sizeof(SK_Point));
715         
716         stk->nb_points += len - size;
717 }
718
719 void sk_trimStroke(SK_Stroke *stk, int start, int end)
720 {
721         int size = end - start + 1;
722         
723         if (start > 0)
724         {
725                 memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
726         }
727         
728         stk->nb_points = size;
729 }
730
731 void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
732 {
733         SK_Point pt1, pt2;
734         SK_Point *prev, *next;
735         float delta_p[3];
736         int i, total;
737         
738         total = end - start;
739
740         VecSubf(delta_p, p_end, p_start);
741         
742         prev = stk->points + start;
743         next = stk->points + end;
744         
745         VECCOPY(pt1.p, p_start);
746         VECCOPY(pt1.no, prev->no);
747         pt1.mode = prev->mode;
748         pt1.type = prev->type;
749         
750         VECCOPY(pt2.p, p_end);
751         VECCOPY(pt2.no, next->no);
752         pt2.mode = next->mode;
753         pt2.type = next->type;
754         
755         sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
756         sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
757         
758         for (i = 1; i < total; i++)
759         {
760                 float delta = (float)i / (float)total;
761                 float *p = stk->points[start + 1 + i].p;
762
763                 VECCOPY(p, delta_p);
764                 VecMulf(p, delta);
765                 VecAddf(p, p, p_start);
766         } 
767 }
768
769 void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
770 {
771         int offset;
772         int i;
773         
774         /* find first exact points outside of range */
775         for (;start > 0; start--)
776         {
777                 if (stk->points[start].type == PT_EXACT)
778                 {
779                         break;
780                 }
781         }
782         
783         for (;end < stk->nb_points - 1; end++)
784         {
785                 if (stk->points[end].type == PT_EXACT)
786                 {
787                         break;
788                 }
789         }
790         
791         offset = start + 1;
792         
793         for (i = start + 1; i < end; i++)
794         {
795                 if (stk->points[i].type == PT_EXACT)
796                 {
797                         if (offset != i)
798                         {
799                                 memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
800                         }
801
802                         offset++;
803                 }
804         }
805         
806         /* some points were removes, move end of array */
807         if (offset < end)
808         {
809                 int size = stk->nb_points - end;
810                 memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
811                 stk->nb_points = offset + size;
812         }
813 }
814
815 void sk_flattenStroke(SK_Stroke *stk, int start, int end)
816 {
817         float normal[3], distance[3];
818         float limit;
819         int i, total;
820         
821         total = end - start + 1;
822         
823         VECCOPY(normal, stk->points[start].no);
824         
825         VecSubf(distance, stk->points[end].p, stk->points[start].p);
826         Projf(normal, distance, normal);
827         limit = Normalize(normal);
828         
829         for (i = 1; i < total - 1; i++)
830         {
831                 float d = limit * i / total;
832                 float offset[3];
833                 float *p = stk->points[start + i].p;
834
835                 VecSubf(distance, p, stk->points[start].p);
836                 Projf(distance, distance, normal);
837                 
838                 VECCOPY(offset, normal);
839                 VecMulf(offset, d);
840                 
841                 VecSubf(p, p, distance);
842                 VecAddf(p, p, offset);
843         } 
844 }
845
846 void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
847 {
848         if (sketch->active_stroke == stk)
849         {
850                 sketch->active_stroke = NULL;
851         }
852         
853         BLI_remlink(&sketch->strokes, stk);
854         sk_freeStroke(stk);
855 }
856
857 void sk_reverseStroke(SK_Stroke *stk)
858 {
859         SK_Point *old_points = stk->points;
860         int i = 0;
861         
862         sk_allocStrokeBuffer(stk);
863         
864         for (i = 0; i < stk->nb_points; i++)
865         {
866                 sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
867         }
868         
869         MEM_freeN(old_points);
870 }
871
872
873 void sk_cancelStroke(SK_Sketch *sketch)
874 {
875         if (sketch->active_stroke != NULL)
876         {
877                 sk_resetOverdraw(sketch);
878                 sk_removeStroke(sketch, sketch->active_stroke);
879         }
880 }
881
882 /* Apply reverse Chaikin filter to simplify the polyline
883  * */
884 void sk_filterStroke(SK_Stroke *stk, int start, int end)
885 {
886         SK_Point *old_points = stk->points;
887         int nb_points = stk->nb_points;
888         int i, j;
889         
890         return;
891         
892         if (start == -1)
893         {
894                 start = 0;
895                 end = stk->nb_points - 1;
896         }
897
898         sk_allocStrokeBuffer(stk);
899         stk->nb_points = 0;
900         
901         /* adding points before range */
902         for (i = 0; i < start; i++)
903         {
904                 sk_appendStrokePoint(stk, old_points + i);
905         }
906         
907         for (i = start, j = start; i <= end; i++)
908         {
909                 if (i - j == 3)
910                 {
911                         SK_Point pt;
912                         float vec[3];
913                         
914                         sk_copyPoint(&pt, &old_points[j+1]);
915
916                         pt.p[0] = 0;
917                         pt.p[1] = 0;
918                         pt.p[2] = 0;
919                         
920                         VECCOPY(vec, old_points[j].p);
921                         VecMulf(vec, -0.25);
922                         VecAddf(pt.p, pt.p, vec);
923                         
924                         VECCOPY(vec, old_points[j+1].p);
925                         VecMulf(vec,  0.75);
926                         VecAddf(pt.p, pt.p, vec);
927
928                         VECCOPY(vec, old_points[j+2].p);
929                         VecMulf(vec,  0.75);
930                         VecAddf(pt.p, pt.p, vec);
931
932                         VECCOPY(vec, old_points[j+3].p);
933                         VecMulf(vec, -0.25);
934                         VecAddf(pt.p, pt.p, vec);
935                         
936                         sk_appendStrokePoint(stk, &pt);
937
938                         j += 2;
939                 }
940                 
941                 /* this might be uneeded when filtering last continuous stroke */
942                 if (old_points[i].type == PT_EXACT)
943                 {
944                         sk_appendStrokePoint(stk, old_points + i);
945                         j = i;
946                 }
947         } 
948         
949         /* adding points after range */
950         for (i = end + 1; i < nb_points; i++)
951         {
952                 sk_appendStrokePoint(stk, old_points + i);
953         }
954
955         MEM_freeN(old_points);
956
957         sk_shrinkStrokeBuffer(stk);
958 }
959
960 void sk_filterLastContinuousStroke(SK_Stroke *stk)
961 {
962         int start, end;
963         
964         end = stk->nb_points -1;
965         
966         for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
967         {
968                 /* nothing to do here*/
969         }
970         
971         if (end - start > 1)
972         {
973                 sk_filterStroke(stk, start, end);
974         }
975 }
976
977 SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
978 {
979         SK_Point *pt = NULL;
980         
981         if (stk->nb_points > 0)
982         {
983                 pt = stk->points + (stk->nb_points - 1);
984         }
985         
986         return pt;
987 }
988
989 void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
990 {
991         float rgb[3];
992         int i;
993         
994         if (id != -1)
995         {
996                 glLoadName(id);
997                 
998                 glBegin(GL_LINE_STRIP);
999                 
1000                 for (i = 0; i < stk->nb_points; i++)
1001                 {
1002                         glVertex3fv(stk->points[i].p);
1003                 }
1004                 
1005                 glEnd();
1006                 
1007         }
1008         else
1009         {
1010                 float d_rgb[3] = {1, 1, 1};
1011                 
1012                 VECCOPY(rgb, color);
1013                 VecSubf(d_rgb, d_rgb, rgb);
1014                 VecMulf(d_rgb, 1.0f / (float)stk->nb_points);
1015                 
1016                 glBegin(GL_LINE_STRIP);
1017
1018                 for (i = 0; i < stk->nb_points; i++)
1019                 {
1020                         if (i >= start && i <= end)
1021                         {
1022                                 glColor3f(0.3, 0.3, 0.3);
1023                         }
1024                         else
1025                         {
1026                                 glColor3fv(rgb);
1027                         }
1028                         glVertex3fv(stk->points[i].p);
1029                         VecAddf(rgb, rgb, d_rgb);
1030                 }
1031                 
1032                 glEnd();
1033         
1034                 glColor3f(0, 0, 0);
1035                 glBegin(GL_POINTS);
1036         
1037                 for (i = 0; i < stk->nb_points; i++)
1038                 {
1039                         if (stk->points[i].type == PT_EXACT)
1040                         {
1041                                 glVertex3fv(stk->points[i].p);
1042                         }
1043                 }
1044                 
1045                 glEnd();
1046         }
1047
1048 //      glColor3f(1, 1, 1);
1049 //      glBegin(GL_POINTS);
1050 //
1051 //      for (i = 0; i < stk->nb_points; i++)
1052 //      {
1053 //              if (stk->points[i].type == PT_CONTINUOUS)
1054 //              {
1055 //                      glVertex3fv(stk->points[i].p);
1056 //              }
1057 //      }
1058 //
1059 //      glEnd();
1060 }
1061
1062 void drawSubdividedStrokeBy(bContext *C, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
1063 {
1064         float head[3], tail[3];
1065         int bone_start = 0;
1066         int end = iter->length;
1067         int index;
1068
1069         iter->head(iter);
1070         VECCOPY(head, iter->p);
1071         
1072         glColor3f(0, 1, 0);
1073         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2);
1074         glBegin(GL_POINTS);
1075         
1076         index = next_subdividion(C, iter, bone_start, end, head, tail);
1077         while (index != -1)
1078         {
1079                 glVertex3fv(tail);
1080                 
1081                 VECCOPY(head, tail);
1082                 bone_start = index; // start next bone from current index
1083
1084                 index = next_subdividion(C, iter, bone_start, end, head, tail);
1085         }
1086         
1087         glEnd();
1088         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1089 }
1090
1091 void sk_drawStrokeSubdivision(bContext *C, SK_Stroke *stk)
1092 {
1093         Scene *scene = CTX_data_scene(C);
1094         int head_index = -1;
1095         int i;
1096         
1097         if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
1098         {
1099                 return;
1100         }
1101
1102         
1103         for (i = 0; i < stk->nb_points; i++)
1104         {
1105                 SK_Point *pt = stk->points + i;
1106                 
1107                 if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
1108                 {
1109                         if (head_index == -1)
1110                         {
1111                                 head_index = i;
1112                         }
1113                         else
1114                         {
1115                                 if (i - head_index > 1)
1116                                 {
1117                                         SK_StrokeIterator sk_iter;
1118                                         BArcIterator *iter = (BArcIterator*)&sk_iter;
1119                                         
1120                                         initStrokeIterator(iter, stk, head_index, i);
1121
1122                                         if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1123                                         {
1124                                                 drawSubdividedStrokeBy(C, iter, nextAdaptativeSubdivision);
1125                                         }
1126                                         else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1127                                         {
1128                                                 drawSubdividedStrokeBy(C, iter, nextLengthSubdivision);
1129                                         }
1130                                         else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1131                                         {
1132                                                 drawSubdividedStrokeBy(C, iter, nextFixedSubdivision);
1133                                         }
1134                                         
1135                                 }
1136
1137                                 head_index = i;
1138                         }
1139                 }
1140         }       
1141 }
1142
1143 SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts)
1144 {
1145         ARegion *ar = CTX_wm_region(C);
1146         SK_Point *pt = NULL;
1147         int i;
1148         
1149         for (i = 0; i < stk->nb_points; i++)
1150         {
1151                 if (all_pts || stk->points[i].type == PT_EXACT)
1152                 {
1153                         short pval[2];
1154                         int pdist;
1155                         
1156                         project_short_noclip(ar, stk->points[i].p, pval);
1157                         
1158                         pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1159                         
1160                         if (pdist < *dist)
1161                         {
1162                                 *dist = pdist;
1163                                 pt = stk->points + i;
1164                                 
1165                                 if (index != NULL)
1166                                 {
1167                                         *index = i;
1168                                 }
1169                         }
1170                 }
1171         }
1172         
1173         return pt;
1174 }
1175
1176 SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, short mval[2], int *dist)
1177 {
1178         ARegion *ar = CTX_wm_region(C);
1179         SK_Point *pt = NULL;
1180         EditBone *bone;
1181         
1182         for (bone = ebones->first; bone; bone = bone->next)
1183         {
1184                 float vec[3];
1185                 short pval[2];
1186                 int pdist;
1187                 
1188                 if ((bone->flag & BONE_CONNECTED) == 0)
1189                 {
1190                         VECCOPY(vec, bone->head);
1191                         Mat4MulVecfl(ob->obmat, vec);
1192                         project_short_noclip(ar, vec, pval);
1193                         
1194                         pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1195                         
1196                         if (pdist < *dist)
1197                         {
1198                                 *dist = pdist;
1199                                 pt = &boneSnap;
1200                                 VECCOPY(pt->p, vec);
1201                                 pt->type = PT_EXACT;
1202                         }
1203                 }
1204                 
1205                 
1206                 VECCOPY(vec, bone->tail);
1207                 Mat4MulVecfl(ob->obmat, vec);
1208                 project_short_noclip(ar, vec, pval);
1209                 
1210                 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1211                 
1212                 if (pdist < *dist)
1213                 {
1214                         *dist = pdist;
1215                         pt = &boneSnap;
1216                         VECCOPY(pt->p, vec);
1217                         pt->type = PT_EXACT;
1218                 }
1219         }
1220         
1221         return pt;
1222 }
1223
1224 void sk_resetOverdraw(SK_Sketch *sketch)
1225 {
1226         sketch->over.target = NULL;
1227         sketch->over.start = -1;
1228         sketch->over.end = -1;
1229         sketch->over.count = 0;
1230 }
1231
1232 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
1233 {
1234         return  sketch->over.target &&
1235                         sketch->over.count >= SK_OVERDRAW_LIMIT &&
1236                         (sketch->over.target == stk || stk == NULL) &&
1237                         (sketch->over.start != -1 || sketch->over.end != -1);
1238 }
1239
1240 void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1241 {
1242         if (sketch->over.target == NULL)
1243         {
1244                 SK_Stroke *target;
1245                 int closest_index = -1;
1246                 int dist = SNAP_MIN_DISTANCE * 2;
1247                 
1248                 /* If snapping, don't start overdraw */
1249                 if (sk_lastStrokePoint(stk)->mode == PT_SNAP)
1250                 {
1251                         return;
1252                 }
1253                 
1254                 for (target = sketch->strokes.first; target; target = target->next)
1255                 {
1256                         if (target != stk)
1257                         {
1258                                 int index;
1259                                 
1260                                 SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
1261                                 
1262                                 if (spt != NULL)
1263                                 {
1264                                         sketch->over.target = target;
1265                                         closest_index = index;
1266                                 }
1267                         }
1268                 }
1269                 
1270                 if (sketch->over.target != NULL)
1271                 {
1272                         if (closest_index > -1)
1273                         {
1274                                 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
1275                                 {
1276                                         sketch->over.count = SK_OVERDRAW_LIMIT;
1277                                 }
1278                                 else
1279                                 {
1280                                         sketch->over.count++;
1281                                 }
1282                         }
1283
1284                         if (stk->nb_points == 1)
1285                         {
1286                                 sketch->over.start = closest_index;
1287                         }
1288                         else
1289                         {
1290                                 sketch->over.end = closest_index;
1291                         }
1292                 }
1293         }
1294         else if (sketch->over.target != NULL)
1295         {
1296                 SK_Point *closest_pt = NULL;
1297                 int dist = SNAP_MIN_DISTANCE * 2;
1298                 int index;
1299
1300                 closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
1301                 
1302                 if (closest_pt != NULL)
1303                 {
1304                         if (sk_lastStrokePoint(stk)->type == PT_EXACT)
1305                         {
1306                                 sketch->over.count = SK_OVERDRAW_LIMIT;
1307                         }
1308                         else
1309                         {
1310                                 sketch->over.count++;
1311                         }
1312                         
1313                         sketch->over.end = index;
1314                 }
1315                 else
1316                 {
1317                         sketch->over.end = -1;
1318                 }
1319         }
1320 }
1321
1322 /* return 1 on reverse needed */
1323 int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
1324 {
1325         int retval = 0;
1326
1327         *start = sketch->over.start;
1328         *end = sketch->over.end;
1329         
1330         if (*start == -1)
1331         {
1332                 *start = 0;
1333         }
1334         
1335         if (*end == -1)
1336         {
1337                 *end = sketch->over.target->nb_points - 1;
1338         }
1339         
1340         if (*end < *start)
1341         {
1342                 int tmp = *start;
1343                 *start = *end;
1344                 *end = tmp;
1345                 retval = 1;
1346         }
1347         
1348         return retval;
1349 }
1350
1351 void sk_endOverdraw(SK_Sketch *sketch)
1352 {
1353         SK_Stroke *stk = sketch->active_stroke;
1354         
1355         if (sk_hasOverdraw(sketch, NULL))
1356         {
1357                 int start;
1358                 int end;
1359                 
1360                 if (sk_adjustIndexes(sketch, &start, &end))
1361                 {
1362                         sk_reverseStroke(stk);
1363                 }
1364                 
1365                 if (stk->nb_points > 1)
1366                 {
1367                         stk->points->type = sketch->over.target->points[start].type;
1368                         sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
1369                 }
1370                 
1371                 sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
1372                 
1373                 sk_removeStroke(sketch, stk);
1374                 
1375                 sk_resetOverdraw(sketch);
1376         }
1377 }
1378
1379
1380 void sk_startStroke(SK_Sketch *sketch)
1381 {
1382         SK_Stroke *stk = sk_createStroke();
1383         
1384         BLI_addtail(&sketch->strokes, stk);
1385         sketch->active_stroke = stk;
1386
1387         sk_resetOverdraw(sketch);       
1388 }
1389
1390 void sk_endStroke(bContext *C, SK_Sketch *sketch)
1391 {
1392         Scene *scene = CTX_data_scene(C);
1393         sk_shrinkStrokeBuffer(sketch->active_stroke);
1394
1395         if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
1396         {
1397                 sk_endOverdraw(sketch);
1398         }
1399
1400         sketch->active_stroke = NULL;
1401 }
1402
1403 void sk_updateDrawData(SK_DrawData *dd)
1404 {
1405         dd->type = PT_CONTINUOUS;
1406         
1407         dd->previous_mval[0] = dd->mval[0];
1408         dd->previous_mval[1] = dd->mval[1];
1409 }
1410
1411 float sk_distanceDepth(bContext *C, float p1[3], float p2[3])
1412 {
1413         ARegion *ar = CTX_wm_region(C);
1414         RegionView3D *rv3d = ar->regiondata;
1415         float vec[3];
1416         float distance;
1417         
1418         VecSubf(vec, p1, p2);
1419         
1420         Projf(vec, vec, rv3d->viewinv[2]);
1421         
1422         distance = VecLength(vec);
1423         
1424         if (Inpf(rv3d->viewinv[2], vec) > 0)
1425         {
1426                 distance *= -1;
1427         }
1428         
1429         return distance; 
1430 }
1431
1432 void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance)
1433 {
1434         ARegion *ar = CTX_wm_region(C);
1435         ScrArea *sa = CTX_wm_area(C);
1436         View3D *v3d = sa->spacedata.first;
1437
1438         float progress = 0;
1439         int i;
1440         
1441         progress = VecLenf(stk->points[start].p, stk->points[start - 1].p);
1442         
1443         for (i = start; i <= end; i++)
1444         {
1445                 float ray_start[3], ray_normal[3];
1446                 float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p);
1447                 short pval[2];
1448                 
1449                 project_short_noclip(ar, stk->points[i].p, pval);
1450                 viewray(ar, v3d, pval, ray_start, ray_normal);
1451                 
1452                 VecMulf(ray_normal, distance * progress / length);
1453                 VecAddf(stk->points[i].p, stk->points[i].p, ray_normal);
1454
1455                 progress += delta ;
1456         }
1457 }
1458
1459 void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd)
1460 {
1461         ARegion *ar = CTX_wm_region(C);
1462         /* copied from grease pencil, need fixing */    
1463         SK_Point *last = sk_lastStrokePoint(stk);
1464         short cval[2];
1465         float fp[3] = {0, 0, 0};
1466         float dvec[3];
1467         
1468         if (last != NULL)
1469         {
1470                 VECCOPY(fp, last->p);
1471         }
1472         
1473         initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
1474         
1475         /* method taken from editview.c - mouse_cursor() */
1476         project_short_noclip(ar, fp, cval);
1477         window_to_3d(ar, dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
1478         VecSubf(vec, fp, dvec);
1479 }
1480
1481 int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1482 {
1483         pt->type = dd->type;
1484         pt->mode = PT_PROJECT;
1485         sk_projectDrawPoint(C, pt->p, stk, dd);
1486         
1487         return 1;
1488 }
1489
1490 int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1491 {
1492         SK_Point pt;
1493         
1494         sk_initPoint(C, &pt);
1495         
1496         sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd);
1497
1498         sk_appendStrokePoint(stk, &pt);
1499         
1500         return 1;
1501 }
1502
1503 int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1504 {
1505         Scene *scene = CTX_data_scene(C);
1506         int point_added = 0;
1507
1508         if (scene->snap_mode == SCE_SNAP_MODE_VOLUME)
1509         {
1510                 ListBase depth_peels;
1511                 DepthPeel *p1, *p2;
1512                 float *last_p = NULL;
1513                 float dist = FLT_MAX;
1514                 float p[3];
1515                 
1516                 depth_peels.first = depth_peels.last = NULL;
1517                 
1518                 peelObjectsContext(C, &depth_peels, dd->mval);
1519                 
1520                 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
1521                 {
1522                         last_p = stk->points[stk->nb_points - 1].p;
1523                 }
1524                 else if (LAST_SNAP_POINT_VALID)
1525                 {
1526                         last_p = LAST_SNAP_POINT;
1527                 }
1528                 
1529                 
1530                 for (p1 = depth_peels.first; p1; p1 = p1->next)
1531                 {
1532                         if (p1->flag == 0)
1533                         {
1534                                 float vec[3];
1535                                 float new_dist;
1536                                 
1537                                 p2 = NULL;
1538                                 p1->flag = 1;
1539         
1540                                 /* if peeling objects, take the first and last from each object */                      
1541                                 if (scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
1542                                 {
1543                                         DepthPeel *peel;
1544                                         for (peel = p1->next; peel; peel = peel->next)
1545                                         {
1546                                                 if (peel->ob == p1->ob)
1547                                                 {
1548                                                         peel->flag = 1;
1549                                                         p2 = peel;
1550                                                 }
1551                                         }
1552                                 }
1553                                 /* otherwise, pair first with second and so on */
1554                                 else
1555                                 {
1556                                         for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
1557                                         {
1558                                                 /* nothing to do here */
1559                                         }
1560                                 }
1561                                 
1562                                 if (p2)
1563                                 {
1564                                         p2->flag = 1;
1565                                         
1566                                         VecAddf(vec, p1->p, p2->p);
1567                                         VecMulf(vec, 0.5f);
1568                                 }
1569                                 else
1570                                 {
1571                                         VECCOPY(vec, p1->p);
1572                                 }
1573                                 
1574                                 if (last_p == NULL)
1575                                 {
1576                                         VECCOPY(p, vec);
1577                                         dist = 0;
1578                                         break;
1579                                 }
1580                                 
1581                                 new_dist = VecLenf(last_p, vec);
1582                                 
1583                                 if (new_dist < dist)
1584                                 {
1585                                         VECCOPY(p, vec);
1586                                         dist = new_dist;
1587                                 }
1588                         }
1589                 }
1590                 
1591                 if (dist != FLT_MAX)
1592                 {
1593                         pt->type = dd->type;
1594                         pt->mode = PT_SNAP;
1595                         VECCOPY(pt->p, p);
1596                         
1597                         point_added = 1;
1598                 }
1599                 
1600                 BLI_freelistN(&depth_peels);
1601         }
1602         else
1603         {
1604                 SK_Stroke *snap_stk;
1605                 float vec[3];
1606                 float no[3];
1607                 int found = 0;
1608                 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
1609
1610                 /* snap to strokes */
1611                 // if (scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
1612                 for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
1613                 {
1614                         SK_Point *spt = NULL;
1615                         if (snap_stk == stk)
1616                         {
1617                                 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
1618                         }
1619                         else
1620                         {
1621                                 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
1622                         }
1623                                 
1624                         if (spt != NULL)
1625                         {
1626                                 VECCOPY(pt->p, spt->p);
1627                                 point_added = 1;
1628                         }
1629                 }
1630
1631                 /* try to snap to closer object */
1632                 found = snapObjectsContext(C, dd->mval, &dist, vec, no, SNAP_NOT_SELECTED);
1633                 if (found == 1)
1634                 {
1635                         pt->type = dd->type;
1636                         pt->mode = PT_SNAP;
1637                         VECCOPY(pt->p, vec);
1638                         
1639                         point_added = 1;
1640                 }
1641         }
1642         
1643         return point_added;
1644 }
1645
1646 int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1647 {
1648         int point_added;
1649         SK_Point pt;
1650         
1651         sk_initPoint(C, &pt);
1652
1653         point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
1654         
1655         if (point_added)
1656         {
1657                 float final_p[3];
1658                 float length, distance;
1659                 int total;
1660                 int i;
1661                 
1662                 VECCOPY(final_p, pt.p);
1663                 
1664                 sk_projectDrawPoint(C, pt.p, stk, dd);
1665                 sk_appendStrokePoint(stk, &pt);
1666                 
1667                 /* update all previous point to give smooth Z progresion */
1668                 total = 0;
1669                 length = 0;
1670                 for (i = stk->nb_points - 2; i > 0; i--)
1671                 {
1672                         length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
1673                         total++;
1674                         if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
1675                         {
1676                                 break;
1677                         }
1678                 }
1679                 
1680                 if (total > 1)
1681                 {
1682                         distance = sk_distanceDepth(C, final_p, stk->points[i].p);
1683                         
1684                         sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
1685                 }
1686                 
1687                 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1688                 
1689                 point_added = 1;
1690         }
1691         
1692         return point_added;
1693 }
1694
1695 void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
1696 {
1697         Scene *scene = CTX_data_scene(C);
1698         int point_added = 0;
1699         
1700         if (qual & KM_CTRL)
1701         {
1702                 point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
1703         }
1704         
1705         if (point_added == 0)
1706         {
1707                 point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
1708         }
1709         
1710         if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
1711         {
1712                 sk_updateOverdraw(C, sketch, stk, dd);
1713         }
1714 }
1715
1716 void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
1717 {
1718         int point_added = 0;
1719         
1720         if (qual & KM_CTRL)
1721         {
1722                 point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
1723                 LAST_SNAP_POINT_VALID = 1;
1724                 VECCOPY(LAST_SNAP_POINT, pt->p);
1725         }
1726         else
1727         {
1728                 LAST_SNAP_POINT_VALID = 0;
1729         }
1730         
1731         if (point_added == 0)
1732         {
1733                 point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
1734         }       
1735 }
1736
1737 void sk_endContinuousStroke(SK_Stroke *stk)
1738 {
1739         stk->points[stk->nb_points - 1].type = PT_EXACT;
1740 }
1741
1742 void sk_updateNextPoint(SK_Sketch *sketch)
1743 {
1744         if (sketch->active_stroke)
1745         {
1746                 SK_Stroke *stk = sketch->active_stroke;
1747                 memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
1748         }
1749 }
1750
1751 int sk_stroke_filtermval(SK_DrawData *dd)
1752 {
1753         int retval = 0;
1754         if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist)
1755         {
1756                 retval = 1;
1757         }
1758         
1759         return retval;
1760 }
1761
1762 void sk_initDrawData(SK_DrawData *dd)
1763 {
1764 //      XXX
1765 //      getmouseco_areawin(dd->mval);
1766         dd->previous_mval[0] = -1;
1767         dd->previous_mval[1] = -1;
1768         dd->type = PT_EXACT;
1769 }
1770 /********************************************/
1771
1772 static void* headPoint(void *arg);
1773 static void* tailPoint(void *arg);
1774 static void* nextPoint(void *arg);
1775 static void* nextNPoint(void *arg, int n);
1776 static void* peekPoint(void *arg, int n);
1777 static void* previousPoint(void *arg);
1778 static int   iteratorStopped(void *arg);
1779
1780 static void initIteratorFct(SK_StrokeIterator *iter)
1781 {
1782         iter->head = headPoint;
1783         iter->tail = tailPoint;
1784         iter->peek = peekPoint;
1785         iter->next = nextPoint;
1786         iter->nextN = nextNPoint;
1787         iter->previous = previousPoint;
1788         iter->stopped = iteratorStopped;        
1789 }
1790
1791 static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
1792 {
1793         SK_Point *pt = NULL;
1794         
1795         if (index >= 0 && index < iter->length)
1796         {
1797                 pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
1798                 iter->p = pt->p;
1799                 iter->no = pt->no;
1800         }
1801         else
1802         {
1803                 iter->p = NULL;
1804                 iter->no = NULL;
1805         }
1806         
1807         return pt;
1808 }
1809
1810 void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
1811 {
1812         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1813
1814         initIteratorFct(iter);
1815         iter->stroke = stk;
1816         
1817         if (start < end)
1818         {
1819                 iter->start = start + 1;
1820                 iter->end = end - 1;
1821                 iter->stride = 1;
1822         }
1823         else
1824         {
1825                 iter->start = start - 1;
1826                 iter->end = end + 1;
1827                 iter->stride = -1;
1828         }
1829         
1830         iter->length = iter->stride * (iter->end - iter->start + 1);
1831         
1832         iter->index = -1;
1833 }
1834
1835
1836 static void* headPoint(void *arg)
1837 {
1838         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1839         SK_Point *result = NULL;
1840         
1841         result = &(iter->stroke->points[iter->start - iter->stride]);
1842         iter->p = result->p;
1843         iter->no = result->no;
1844         
1845         return result;
1846 }
1847
1848 static void* tailPoint(void *arg)
1849 {
1850         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1851         SK_Point *result = NULL;
1852         
1853         result = &(iter->stroke->points[iter->end + iter->stride]);
1854         iter->p = result->p;
1855         iter->no = result->no;
1856         
1857         return result;
1858 }
1859
1860 static void* nextPoint(void *arg)
1861 {
1862         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1863         SK_Point *result = NULL;
1864         
1865         iter->index++;
1866         if (iter->index < iter->length)
1867         {
1868                 result = setIteratorValues(iter, iter->index);
1869         }
1870
1871         return result;
1872 }
1873
1874 static void* nextNPoint(void *arg, int n)
1875 {
1876         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1877         SK_Point *result = NULL;
1878                 
1879         iter->index += n;
1880
1881         /* check if passed end */
1882         if (iter->index < iter->length)
1883         {
1884                 result = setIteratorValues(iter, iter->index);
1885         }
1886
1887         return result;
1888 }
1889
1890 static void* peekPoint(void *arg, int n)
1891 {
1892         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1893         SK_Point *result = NULL;
1894         int index = iter->index + n;
1895
1896         /* check if passed end */
1897         if (index < iter->length)
1898         {
1899                 result = setIteratorValues(iter, index);
1900         }
1901
1902         return result;
1903 }
1904
1905 static void* previousPoint(void *arg)
1906 {
1907         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1908         SK_Point *result = NULL;
1909         
1910         if (iter->index > 0)
1911         {
1912                 iter->index--;
1913                 result = setIteratorValues(iter, iter->index);
1914         }
1915
1916         return result;
1917 }
1918
1919 static int iteratorStopped(void *arg)
1920 {
1921         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1922
1923         if (iter->index >= iter->length)
1924         {
1925                 return 1;
1926         }
1927         else
1928         {
1929                 return 0;
1930         }
1931 }
1932
1933 void sk_convertStroke(bContext *C, SK_Stroke *stk)
1934 {
1935         Object *obedit = CTX_data_edit_object(C);
1936         Scene *scene = CTX_data_scene(C);
1937         bArmature *arm = obedit->data;
1938         SK_Point *head;
1939         EditBone *parent = NULL;
1940         float invmat[4][4]; /* move in caller function */
1941         float tmat[3][3];
1942         int head_index = 0;
1943         int i;
1944         
1945         head = NULL;
1946         
1947         Mat4Invert(invmat, obedit->obmat);
1948         
1949         Mat3CpyMat4(tmat, obedit->obmat);
1950         Mat3Transp(tmat);
1951         
1952         for (i = 0; i < stk->nb_points; i++)
1953         {
1954                 SK_Point *pt = stk->points + i;
1955                 
1956                 if (pt->type == PT_EXACT)
1957                 {
1958                         if (head == NULL)
1959                         {
1960                                 head_index = i;
1961                                 head = pt;
1962                         }
1963                         else
1964                         {
1965                                 EditBone *bone = NULL;
1966                                 EditBone *new_parent;
1967                                 
1968                                 if (i - head_index > 1)
1969                                 {
1970                                         SK_StrokeIterator sk_iter;
1971                                         BArcIterator *iter = (BArcIterator*)&sk_iter;
1972
1973                                         initStrokeIterator(iter, stk, head_index, i);
1974                                         
1975                                         if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1976                                         {
1977                                                 bone = subdivideArcBy(C, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
1978                                         }
1979                                         else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1980                                         {
1981                                                 bone = subdivideArcBy(C, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
1982                                         }
1983                                         else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1984                                         {
1985                                                 bone = subdivideArcBy(C, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
1986                                         }
1987                                 }
1988                                 
1989                                 if (bone == NULL)
1990                                 {
1991                                         bone = addEditBone(arm, "Bone");
1992                                         
1993                                         VECCOPY(bone->head, head->p);
1994                                         VECCOPY(bone->tail, pt->p);
1995
1996                                         Mat4MulVecfl(invmat, bone->head);
1997                                         Mat4MulVecfl(invmat, bone->tail);
1998                                         setBoneRollFromNormal(bone, pt->no, invmat, tmat);
1999                                 }
2000                                 
2001                                 new_parent = bone;
2002                                 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
2003                                 
2004                                 /* move to end of chain */
2005                                 while (bone->parent != NULL)
2006                                 {
2007                                         bone = bone->parent;
2008                                         bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
2009                                 }
2010
2011                                 if (parent != NULL)
2012                                 {
2013                                         bone->parent = parent;
2014                                         bone->flag |= BONE_CONNECTED;                                   
2015                                 }
2016                                 
2017                                 parent = new_parent;
2018                                 head_index = i;
2019                                 head = pt;
2020                         }
2021                 }
2022         }
2023 }
2024
2025 void sk_convert(bContext *C, SK_Sketch *sketch)
2026 {
2027         Scene *scene = CTX_data_scene(C);
2028         SK_Stroke *stk;
2029         
2030         for (stk = sketch->strokes.first; stk; stk = stk->next)
2031         {
2032                 if (stk->selected == 1)
2033                 {
2034                         if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
2035                         {
2036                                 sk_retargetStroke(C, stk);
2037                         }
2038                         else
2039                         {
2040                                 sk_convertStroke(C, stk);
2041                         }
2042 //                      XXX
2043 //                      allqueue(REDRAWBUTSEDIT, 0);
2044                 }
2045         }
2046 }
2047 /******************* GESTURE *************************/
2048
2049
2050 /* returns the number of self intersections */
2051 int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
2052 {
2053         ARegion *ar = CTX_wm_region(C);
2054         int added = 0;
2055         int s_i;
2056
2057         for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
2058         {
2059                 float s_p1[3] = {0, 0, 0};
2060                 float s_p2[3] = {0, 0, 0};
2061                 int g_i;
2062                 
2063                 project_float(ar, gesture->points[s_i].p, s_p1);
2064                 project_float(ar, gesture->points[s_i + 1].p, s_p2);
2065
2066                 /* start checking from second next, because two consecutive cannot intersect */
2067                 for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
2068                 {
2069                         float g_p1[3] = {0, 0, 0};
2070                         float g_p2[3] = {0, 0, 0};
2071                         float vi[3];
2072                         float lambda;
2073                         
2074                         project_float(ar, gesture->points[g_i].p, g_p1);
2075                         project_float(ar, gesture->points[g_i + 1].p, g_p2);
2076                         
2077                         if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
2078                         {
2079                                 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
2080                                 
2081                                 isect->gesture_index = g_i;
2082                                 isect->before = s_i;
2083                                 isect->after = s_i + 1;
2084                                 isect->stroke = gesture;
2085                                 
2086                                 VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
2087                                 VecMulf(isect->p, lambda);
2088                                 VecAddf(isect->p, isect->p, gesture->points[s_i].p);
2089                                 
2090                                 BLI_addtail(list, isect);
2091
2092                                 added++;
2093                         }
2094                 }
2095         }
2096         
2097         return added;
2098 }
2099
2100 int cmpIntersections(void *i1, void *i2)
2101 {
2102         SK_Intersection *isect1 = i1, *isect2 = i2;
2103         
2104         if (isect1->stroke == isect2->stroke)
2105         {
2106                 if (isect1->before < isect2->before)
2107                 {
2108                         return -1;
2109                 }
2110                 else if (isect1->before > isect2->before)
2111                 {
2112                         return 1;
2113                 }
2114                 else
2115                 {
2116                         if (isect1->lambda < isect2->lambda)
2117                         {
2118                                 return -1;
2119                         }
2120                         else if (isect1->lambda > isect2->lambda)
2121                         {
2122                                 return 1;
2123                         }
2124                 }
2125         }
2126         
2127         return 0;
2128 }
2129
2130
2131 /* returns the maximum number of intersections per stroke */
2132 int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
2133 {
2134         ARegion *ar = CTX_wm_region(C);
2135         ScrArea *sa = CTX_wm_area(C);
2136         View3D *v3d = sa->spacedata.first;
2137         SK_Stroke *stk;
2138         int added = 0;
2139
2140         for (stk = sketch->strokes.first; stk; stk = stk->next)
2141         {
2142                 int s_added = 0;
2143                 int s_i;
2144                 
2145                 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
2146                 {
2147                         float s_p1[3] = {0, 0, 0};
2148                         float s_p2[3] = {0, 0, 0};
2149                         int g_i;
2150                         
2151                         project_float(ar, stk->points[s_i].p, s_p1);
2152                         project_float(ar, stk->points[s_i + 1].p, s_p2);
2153
2154                         for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
2155                         {
2156                                 float g_p1[3] = {0, 0, 0};
2157                                 float g_p2[3] = {0, 0, 0};
2158                                 float vi[3];
2159                                 float lambda;
2160                                 
2161                                 project_float(ar, gesture->points[g_i].p, g_p1);
2162                                 project_float(ar, gesture->points[g_i + 1].p, g_p2);
2163                                 
2164                                 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
2165                                 {
2166                                         SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
2167                                         float ray_start[3], ray_end[3];
2168                                         short mval[2];
2169                                         
2170                                         isect->gesture_index = g_i;
2171                                         isect->before = s_i;
2172                                         isect->after = s_i + 1;
2173                                         isect->stroke = stk;
2174                                         isect->lambda = lambda;
2175                                         
2176                                         mval[0] = (short)(vi[0]);
2177                                         mval[1] = (short)(vi[1]);
2178                                         viewline(ar, v3d, mval, ray_start, ray_end);
2179                                         
2180                                         LineIntersectLine(      stk->points[s_i].p,
2181                                                                                 stk->points[s_i + 1].p,
2182                                                                                 ray_start,
2183                                                                                 ray_end,
2184                                                                                 isect->p,
2185                                                                                 vi);
2186                                         
2187                                         BLI_addtail(list, isect);
2188
2189                                         s_added++;
2190                                 }
2191                         }
2192                 }
2193                 
2194                 added = MAX2(s_added, added);
2195         }
2196         
2197         BLI_sortlist(list, cmpIntersections);
2198         
2199         return added;
2200 }
2201
2202 int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
2203 {
2204         SK_StrokeIterator sk_iter;
2205         BArcIterator *iter = (BArcIterator*)&sk_iter;
2206         
2207         float CORRELATION_THRESHOLD = 0.99f;
2208         float *vec;
2209         int i, j;
2210         
2211         sk_appendStrokePoint(segments, &gesture->points[0]);
2212         vec = segments->points[segments->nb_points - 1].p;
2213
2214         initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
2215
2216         for (i = 1, j = 0; i < gesture->nb_points; i++)
2217         { 
2218                 float n[3];
2219                 
2220                 /* Calculate normal */
2221                 VecSubf(n, gesture->points[i].p, vec);
2222                 
2223                 if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
2224                 {
2225                         j = i - 1;
2226                         sk_appendStrokePoint(segments, &gesture->points[j]);
2227                         vec = segments->points[segments->nb_points - 1].p;
2228                         segments->points[segments->nb_points - 1].type = PT_EXACT;
2229                 }
2230         }
2231
2232         sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
2233         
2234         return segments->nb_points - 1;
2235 }
2236
2237 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2238 {
2239         if (gest->nb_segments == 1 && gest->nb_intersections == 1)
2240         {
2241                 return 1;
2242         }
2243
2244         return 0;
2245 }
2246
2247 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2248 {
2249         SK_Intersection *isect;
2250         
2251         for (isect = gest->intersections.first; isect; isect = isect->next)
2252         {
2253                 SK_Point pt;
2254                 
2255                 pt.type = PT_EXACT;
2256                 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
2257                 VECCOPY(pt.p, isect->p);
2258                 
2259                 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
2260         }
2261 }
2262
2263 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2264 {
2265         if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
2266         {
2267                 float s1[3], s2[3];
2268                 float angle;
2269                 
2270                 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
2271                 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
2272                 
2273                 angle = VecAngle2(s1, s2);
2274         
2275                 if (angle > 60 && angle < 120)
2276                 {
2277                         return 1;
2278                 }
2279         }
2280
2281         return 0;
2282 }
2283
2284 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2285 {
2286         SK_Intersection *isect;
2287         float trim_dir[3];
2288         
2289         VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
2290         
2291         for (isect = gest->intersections.first; isect; isect = isect->next)
2292         {
2293                 SK_Point pt;
2294                 float stroke_dir[3];
2295                 
2296                 pt.type = PT_EXACT;
2297                 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
2298                 VECCOPY(pt.p, isect->p);
2299                 
2300                 VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
2301                 
2302                 /* same direction, trim end */
2303                 if (Inpf(stroke_dir, trim_dir) > 0)
2304                 {
2305                         sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
2306                         sk_trimStroke(isect->stroke, 0, isect->after);
2307                 }
2308                 /* else, trim start */
2309                 else
2310                 {
2311                         sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
2312                         sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
2313                 }
2314         
2315         }
2316 }
2317
2318 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2319 {
2320         if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
2321         {
2322                 SK_Intersection *isect, *self_isect;
2323                 
2324                 /* get the the last intersection of the first pair */
2325                 for( isect = gest->intersections.first; isect; isect = isect->next )
2326                 {
2327                         if (isect->stroke == isect->next->stroke)
2328                         {
2329                                 isect = isect->next;
2330                                 break;
2331                         }
2332                 }
2333                 
2334                 self_isect = gest->self_intersections.first;
2335                 
2336                 if (isect && isect->gesture_index < self_isect->gesture_index)
2337                 {
2338                         return 1;
2339                 }
2340         }
2341         
2342         return 0;
2343 }
2344
2345 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2346 {
2347         SK_Intersection *isect;
2348         int command = 1;
2349         
2350 //      XXX
2351 //      command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
2352         if(command < 1) return;
2353
2354         for (isect = gest->intersections.first; isect; isect = isect->next)
2355         {
2356                 SK_Intersection *i2;
2357                 
2358                 i2 = isect->next;
2359                 
2360                 if (i2 && i2->stroke == isect->stroke)
2361                 {
2362                         switch (command)
2363                         {
2364                                 case 1:
2365                                         sk_flattenStroke(isect->stroke, isect->before, i2->after);
2366                                         break;
2367                                 case 2:
2368                                         sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
2369                                         break;
2370                                 case 3:
2371                                         sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
2372                                         break;
2373                         }
2374
2375                         isect = i2;
2376                 }
2377         }
2378 }
2379
2380 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2381 {
2382         if (gest->nb_segments == 2 && gest->nb_intersections == 2)
2383         {
2384                 float s1[3], s2[3];
2385                 float angle;
2386                 
2387                 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
2388                 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
2389                 
2390                 angle = VecAngle2(s1, s2);
2391                 
2392                 if (angle > 120)
2393                 {
2394                         return 1;
2395                 }
2396         }
2397         
2398         return 0;
2399 }
2400
2401 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2402 {
2403         SK_Intersection *isect;
2404         
2405         for (isect = gest->intersections.first; isect; isect = isect->next)
2406         {
2407                 /* only delete strokes that are crossed twice */
2408                 if (isect->next && isect->next->stroke == isect->stroke)
2409                 {
2410                         isect = isect->next;
2411                         
2412                         sk_removeStroke(sketch, isect->stroke);
2413                 }
2414         }
2415 }
2416
2417 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2418 {
2419         ARegion *ar = CTX_wm_region(C);
2420         if (gest->nb_segments > 2 && gest->nb_intersections == 2)
2421         {
2422                 short start_val[2], end_val[2];
2423                 short dist;
2424                 
2425                 project_short_noclip(ar, gest->stk->points[0].p, start_val);
2426                 project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
2427                 
2428                 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
2429                 
2430                 /* if gesture is a circle */
2431                 if ( dist <= 20 )
2432                 {
2433                         SK_Intersection *isect;
2434                         
2435                         /* check if it circled around an exact point */
2436                         for (isect = gest->intersections.first; isect; isect = isect->next)
2437                         {
2438                                 /* only delete strokes that are crossed twice */
2439                                 if (isect->next && isect->next->stroke == isect->stroke)
2440                                 {
2441                                         int start_index, end_index;
2442                                         int i;
2443                                         
2444                                         start_index = MIN2(isect->after, isect->next->after);
2445                                         end_index = MAX2(isect->before, isect->next->before);
2446         
2447                                         for (i = start_index; i <= end_index; i++)
2448                                         {
2449                                                 if (isect->stroke->points[i].type == PT_EXACT)
2450                                                 {
2451                                                         return 1; /* at least one exact point found, stop detect here */
2452                                                 }
2453                                         }
2454         
2455                                         /* skip next */                         
2456                                         isect = isect->next;
2457                                 }
2458                         }
2459                 }
2460         }
2461                                 
2462         return 0;
2463 }
2464
2465 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2466 {
2467         SK_Intersection *isect;
2468         
2469         /* check if it circled around an exact point */
2470         for (isect = gest->intersections.first; isect; isect = isect->next)
2471         {
2472                 /* only merge strokes that are crossed twice */
2473                 if (isect->next && isect->next->stroke == isect->stroke)
2474                 {
2475                         int start_index, end_index;
2476                         int i;
2477                         
2478                         start_index = MIN2(isect->after, isect->next->after);
2479                         end_index = MAX2(isect->before, isect->next->before);
2480
2481                         for (i = start_index; i <= end_index; i++)
2482                         {
2483                                 /* if exact, switch to continuous */
2484                                 if (isect->stroke->points[i].type == PT_EXACT)
2485                                 {
2486                                         isect->stroke->points[i].type = PT_CONTINUOUS;
2487                                 }
2488                         }
2489
2490                         /* skip next */                         
2491                         isect = isect->next;
2492                 }
2493         }
2494 }
2495
2496 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2497 {
2498         if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
2499         {
2500                 SK_Intersection *isect;
2501                 
2502                 /* check if it circled around an exact point */
2503                 for (isect = gest->intersections.first; isect; isect = isect->next)
2504                 {
2505                         /* only delete strokes that are crossed twice */
2506                         if (isect->next && isect->next->stroke == isect->stroke)
2507                         {
2508                                 float start_v[3], end_v[3];
2509                                 float angle;
2510                                 
2511                                 if (isect->gesture_index < isect->next->gesture_index)
2512                                 {
2513                                         VecSubf(start_v, isect->p, gest->stk->points[0].p);
2514                                         VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
2515                                 }
2516                                 else
2517                                 {
2518                                         VecSubf(start_v, isect->next->p, gest->stk->points[0].p);
2519                                         VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
2520                                 }
2521                                 
2522                                 angle = VecAngle2(start_v, end_v);
2523                                 
2524                                 if (angle > 120)
2525                                 {
2526                                         return 1;
2527                                 }
2528         
2529                                 /* skip next */                         
2530                                 isect = isect->next;
2531                         }
2532                 }
2533         }
2534                 
2535         return 0;
2536 }
2537
2538 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2539 {
2540         SK_Intersection *isect;
2541         
2542         for (isect = gest->intersections.first; isect; isect = isect->next)
2543         {
2544                 /* only reverse strokes that are crossed twice */
2545                 if (isect->next && isect->next->stroke == isect->stroke)
2546                 {
2547                         sk_reverseStroke(isect->stroke);
2548
2549                         /* skip next */                         
2550                         isect = isect->next;
2551                 }
2552         }
2553 }
2554
2555 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2556 {
2557         if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
2558         {
2559                 return 1;
2560         }
2561         return 0;
2562 }
2563
2564 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2565 {
2566         sk_convert(C, sketch);
2567 }
2568
2569 static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2570 {
2571         gest->intersections.first = gest->intersections.last = NULL;
2572         gest->self_intersections.first = gest->self_intersections.last = NULL;
2573         
2574         gest->segments = sk_createStroke();
2575         gest->stk = sketch->gesture;
2576
2577         gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
2578         gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
2579         gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
2580 }
2581
2582 static void sk_freeGesture(SK_Gesture *gest)
2583 {
2584         sk_freeStroke(gest->segments);
2585         BLI_freelistN(&gest->intersections);
2586         BLI_freelistN(&gest->self_intersections);
2587 }
2588
2589 void sk_applyGesture(bContext *C, SK_Sketch *sketch)
2590 {
2591         SK_Gesture gest;
2592         SK_GestureAction *act;
2593         
2594         sk_initGesture(C, &gest, sketch);
2595         
2596         /* detect and apply */
2597         for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
2598         {
2599                 if (act->detect(C, &gest, sketch))
2600                 {
2601                         act->apply(C, &gest, sketch);
2602                         break;
2603                 }
2604         }
2605         
2606         sk_freeGesture(&gest);
2607 }
2608
2609 /********************************************/
2610
2611 void sk_deleteSelectedStrokes(SK_Sketch *sketch)
2612 {
2613         SK_Stroke *stk, *next;
2614         
2615         for (stk = sketch->strokes.first; stk; stk = next)
2616         {
2617                 next = stk->next;
2618                 
2619                 if (stk->selected == 1)
2620                 {
2621                         sk_removeStroke(sketch, stk);
2622                 }
2623         }
2624 }
2625
2626 void sk_selectAllSketch(SK_Sketch *sketch, int mode)
2627 {
2628         SK_Stroke *stk = NULL;
2629         
2630         if (mode == -1)
2631         {
2632                 for (stk = sketch->strokes.first; stk; stk = stk->next)
2633                 {
2634                         stk->selected = 0;
2635                 }
2636         }
2637         else if (mode == 0)
2638         {
2639                 for (stk = sketch->strokes.first; stk; stk = stk->next)
2640                 {
2641                         stk->selected = 1;
2642                 }
2643         }
2644         else if (mode == 1)
2645         {
2646                 int selected = 1;
2647                 
2648                 for (stk = sketch->strokes.first; stk; stk = stk->next)
2649                 {
2650                         selected &= stk->selected;
2651                 }
2652                 
2653                 selected ^= 1;
2654
2655                 for (stk = sketch->strokes.first; stk; stk = stk->next)
2656                 {
2657                         stk->selected = selected;
2658                 }
2659         }
2660 }
2661
2662 void sk_selectStroke(SK_Sketch *sketch, short mval[2], int extend)
2663 {
2664         unsigned int buffer[MAXPICKBUF];
2665         short hits;
2666
2667 //XXX
2668 #if 0
2669         persp(PERSP_VIEW);
2670
2671         hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-5, mval[1]-5, mval[0]+5, mval[1]+5);
2672         if(hits==0)
2673                 hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-12, mval[1]-12, mval[0]+12, mval[1]+12);
2674                 
2675         if (hits>0)
2676         {
2677                 int besthitresult = -1;
2678                         
2679                 if(hits == 1) {
2680                         besthitresult = buffer[3];
2681                 }
2682                 else {
2683                         besthitresult = buffer[3];
2684                         /* loop and get best hit */
2685                 }
2686                 
2687                 if (besthitresult > 0)
2688                 {
2689                         SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
2690                         
2691                         if (extend == 0)
2692                         {
2693                                 sk_selectAllSketch(sketch, -1);
2694                                 
2695                                 selected_stk->selected = 1;
2696                         }
2697                         else
2698                         {
2699                                 selected_stk->selected ^= 1;
2700                         }
2701                         
2702                         
2703                 }
2704         }
2705 #endif
2706 }
2707
2708 void sk_queueRedrawSketch(SK_Sketch *sketch)
2709 {
2710         if (sketch->active_stroke != NULL)
2711         {
2712                 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2713                 
2714                 if (last != NULL)
2715                 {
2716 //                      XXX
2717 //                      allqueue(REDRAWVIEW3D, 0);
2718                 }
2719         }
2720 }
2721
2722 void sk_drawSketch(bContext *C, SK_Sketch *sketch, int with_names)
2723 {
2724         Scene *scene = CTX_data_scene(C);
2725         SK_Stroke *stk;
2726         short qual = 0;
2727         
2728         glDisable(GL_DEPTH_TEST);
2729
2730         glLineWidth(UI_GetThemeValuef(TH_VERTEX_SIZE));
2731         glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
2732         
2733         if (with_names)
2734         {
2735                 int id;
2736                 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
2737                 {
2738                         sk_drawStroke(stk, id, NULL, -1, -1);
2739                 }
2740                 
2741                 glLoadName(-1);
2742         }
2743         else
2744         {
2745                 float selected_rgb[3] = {1, 0, 0};
2746                 float unselected_rgb[3] = {1, 0.5, 0};
2747                 
2748                 for (stk = sketch->strokes.first; stk; stk = stk->next)
2749                 {
2750                         int start = -1;
2751                         int end = -1;
2752                         
2753                         if (sk_hasOverdraw(sketch, stk))
2754                         {
2755                                 sk_adjustIndexes(sketch, &start, &end);
2756                         }
2757                         
2758                         sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
2759                 
2760                         if (stk->selected == 1)
2761                         {
2762                                 sk_drawStrokeSubdivision(C, stk);
2763                         }
2764                 }
2765         
2766                 /* only draw gesture in active area */
2767                 if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
2768                 {
2769                         float gesture_rgb[3] = {0, 0.5, 1};
2770                         sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
2771                 }
2772                 
2773                 if (sketch->active_stroke != NULL)
2774                 {
2775                         SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2776                         
2777                         if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2778                         {
2779                                 sk_drawStrokeSubdivision(C, sketch->active_stroke);
2780                         }
2781                         
2782                         if (last != NULL)
2783                         {
2784                                 /* update point if in active area */
2785                                 if (1 /*area_is_active_area(G.vd->area)*/)
2786                                 {
2787                                         SK_DrawData dd;
2788                                         
2789                                         sk_initDrawData(&dd);
2790                                         sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, qual);
2791                                 }
2792                                 
2793                                 glEnable(GL_LINE_STIPPLE);
2794                                 glColor3fv(selected_rgb);
2795                                 glBegin(GL_LINE_STRIP);
2796                                 
2797                                         glVertex3fv(last->p);
2798                                         glVertex3fv(sketch->next_point.p);
2799                                 
2800                                 glEnd();
2801                                 
2802                                 glDisable(GL_LINE_STIPPLE);
2803         
2804                                 switch (sketch->next_point.mode)
2805                                 {
2806                                         case PT_SNAP:
2807                                                 glColor3f(0, 1, 0);
2808                                                 break;
2809                                         case PT_PROJECT:
2810                                                 glColor3f(0, 0, 0);
2811                                                 break;
2812                                 }
2813                                 
2814                                 glBegin(GL_POINTS);
2815                                 
2816                                         glVertex3fv(sketch->next_point.p);
2817                                 
2818                                 glEnd();
2819                         }
2820                 }
2821         }
2822         
2823         glLineWidth(1.0);
2824         glPointSize(1.0);
2825
2826         glEnable(GL_DEPTH_TEST);
2827 }
2828
2829 int sk_paint(bContext *C, SK_Sketch *sketch, short mbut)
2830 {
2831         Scene *scene = CTX_data_scene(C);
2832         int retval = 1;
2833         short qual = 0;
2834         
2835         if (mbut == LEFTMOUSE)
2836         {
2837                 SK_DrawData dd;
2838                 if (sketch->active_stroke == NULL)
2839                 {
2840                         sk_startStroke(sketch);
2841                         sk_selectAllSketch(sketch, -1);
2842                         
2843                         sketch->active_stroke->selected = 1;
2844                 }
2845
2846                 sk_initDrawData(&dd);
2847                 
2848                 /* paint loop */
2849                 do {
2850                         /* get current user input */
2851 //                      XXX
2852 //                      getmouseco_areawin(dd.mval);
2853                         
2854                         /* only add current point to buffer if mouse moved (otherwise wait until it does) */
2855                         if (sk_stroke_filtermval(&dd)) {
2856
2857                                 sk_addStrokePoint(C, sketch, sketch->active_stroke, &dd, qual);
2858                                 sk_updateDrawData(&dd);
2859 //                              XXX
2860 //                              force_draw(0);
2861                         }
2862                         else
2863                         {
2864 //                              BIF_wait_for_statechange();
2865                         }
2866                         
2867 //                      while( qtest() ) {
2868 //                              short event, val;
2869 //                              event = extern_qread(&val);
2870 //                      }
2871                         
2872                         /* do mouse checking at the end, so don't check twice, and potentially
2873                          * miss a short tap 
2874                          */
2875                 } while (0 /*get_mbut() & L_MOUSE*/);
2876                 
2877                 sk_endContinuousStroke(sketch->active_stroke);
2878                 sk_filterLastContinuousStroke(sketch->active_stroke);
2879                 sk_updateNextPoint(sketch);
2880         }
2881         else if (mbut == RIGHTMOUSE)
2882         {
2883                 if (sketch->active_stroke != NULL)
2884                 {
2885                         SK_Stroke *stk = sketch->active_stroke;
2886                         
2887                         sk_endStroke(C, sketch);
2888                         
2889                         if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2890                         {
2891                                 if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
2892                                 {
2893                                         sk_retargetStroke(C, stk);
2894                                 }
2895                                 else
2896                                 {
2897                                         sk_convertStroke(C, stk);
2898                                 }
2899 //                              XXX
2900 //                              BIF_undo_push("Convert Sketch");
2901                                 sk_removeStroke(sketch, stk);
2902 //                              XXX
2903 //                              allqueue(REDRAWBUTSEDIT, 0);
2904                         }
2905         
2906 //                      XXX             
2907 //                      allqueue(REDRAWVIEW3D, 0);
2908                 }
2909                 /* no gestures in quick mode */
2910                 else if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2911                 {
2912                         retval = 0; /* return zero for default click behavior */
2913                 }
2914                 else
2915                 {
2916                         SK_DrawData dd;
2917                         sketch->gesture = sk_createStroke();
2918         
2919                         sk_initDrawData(&dd);
2920                         
2921                         /* paint loop */
2922                         do {
2923                                 /* get current user input */
2924 //                              XXX
2925 //                              getmouseco_areawin(dd.mval);
2926                                 
2927                                 /* only add current point to buffer if mouse moved (otherwise wait until it does) */
2928                                 if (sk_stroke_filtermval(&dd)) {
2929
2930                                         sk_addStrokeDrawPoint(C, sketch, sketch->gesture, &dd);
2931                                         sk_updateDrawData(&dd);
2932                                         
2933                                         /* draw only if mouse has moved */
2934                                         if (sketch->gesture->nb_points > 1)
2935                                         {
2936 //                                              XXX
2937 //                                              force_draw(0);
2938                                         }
2939                                 }
2940                                 else
2941                                 {
2942 //                                      BIF_wait_for_statechange();
2943                                 }
2944                                 
2945 //                              while( qtest() ) {
2946 //                                      short event, val;
2947 //                                      event = extern_qread(&val);
2948 //                              }
2949                                 
2950                                 /* do mouse checking at the end, so don't check twice, and potentially
2951                                  * miss a short tap 
2952                                  */
2953                         } while (0 /*get_mbut() & R_MOUSE*/);
2954                         
2955                         sk_endContinuousStroke(sketch->gesture);
2956                         sk_filterLastContinuousStroke(sketch->gesture);
2957                         sk_filterLastContinuousStroke(sketch->gesture);
2958                         sk_filterLastContinuousStroke(sketch->gesture);
2959         
2960                         if (sketch->gesture->nb_points > 1)             
2961                         {
2962                                 /* apply gesture here */
2963                                 sk_applyGesture(C, sketch);
2964                         }
2965         
2966                         sk_freeStroke(sketch->gesture);
2967                         sketch->gesture = NULL;
2968                         
2969 //                      XXX
2970 //                      allqueue(REDRAWVIEW3D, 0);
2971                 }
2972         }
2973         
2974         return retval;
2975 }
2976
2977 void BDR_drawSketchNames(bContext *C)
2978 {
2979         if (BIF_validSketchMode(C))
2980         {
2981                 if (GLOBAL_sketch != NULL)
2982                 {
2983                         sk_drawSketch(C, GLOBAL_sketch, 1);
2984                 }
2985         }
2986 }
2987
2988 void BDR_drawSketch(bContext *C)
2989 {
2990         if (BIF_validSketchMode(C))
2991         {
2992                 if (GLOBAL_sketch != NULL)
2993                 {
2994                         sk_drawSketch(C, GLOBAL_sketch, 0);
2995                 }
2996         }
2997 }
2998
2999 void BIF_endStrokeSketch(bContext *C)
3000 {
3001         if (BIF_validSketchMode(C))
3002         {
3003                 if (GLOBAL_sketch != NULL)
3004                 {
3005                         sk_endStroke(C, GLOBAL_sketch);
3006 //                      allqueue(REDRAWVIEW3D, 0);
3007                 }
3008         }
3009 }
3010
3011 void BIF_cancelStrokeSketch(bContext *C)
3012 {
3013         if (BIF_validSketchMode(C))
3014         {
3015                 if (GLOBAL_sketch != NULL)
3016                 {
3017                         sk_cancelStroke(GLOBAL_sketch);
3018 //                      allqueue(REDRAWVIEW3D, 0);
3019                 }
3020         }
3021 }
3022