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