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