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