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