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