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