soc-2008-mxcurioni: merged changes to revision 23516
[blender.git] / source / blender / editors / armature / editarmature_sketch.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 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_arithb.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         Mat4MulVecfl(imat, node->p);
420
421         VECCOPY(node->no, pt->no);
422         Mat3MulVecfl(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                 Mat4MulVecfl(imat, arc->buckets[i].p);
443
444                 VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
445                 Mat3MulVecfl(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         Mat4Invert(imat, obedit->obmat);
461
462         Mat3CpyMat4(tmat, obedit->obmat);
463         Mat3Transp(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         VecSubf(vec1, pt1->p, pt0->p);
509         length = Normalize(vec1);
510         Crossf(axis, vec2, vec1);
511
512         if (VecIsNull(axis))
513         {
514                 axis[1] = 1;
515         }
516
517         angle = NormalizedVecAngle2(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         Crossf(axis, vec2, pt->no);
532
533         if (VecIsNull(axis))
534         {
535                 axis[1] = 1;
536         }
537
538         angle = NormalizedVecAngle2(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                 VecSubf(d_rgb, d_rgb, rgb);
580                 VecMulf(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                         VecAddf(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                         Mat4MulVecfl(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                 Mat4MulVecfl(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         VecSubf(vec, p1, p2);
981
982         Projf(vec, vec, rv3d->viewinv[2]);
983
984         distance = VecLength(vec);
985
986         if (Inpf(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 = VecLenf(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 = VecLenf(stk->points[i].p, stk->points[i + 1].p);
1009                 short pval[2];
1010
1011                 project_short_noclip(ar, stk->points[i].p, pval);
1012                 viewray(ar, v3d, pval, ray_start, ray_normal);
1013
1014                 VecMulf(ray_normal, distance * progress / length);
1015                 VecAddf(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         VecSubf(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
1080                 BLI_freelistN(&sketch->depth_peels);
1081                 sketch->depth_peels.first = sketch->depth_peels.last = NULL;
1082
1083                 peelObjectsContext(C, &sketch->depth_peels, dd->mval);
1084
1085                 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
1086                 {
1087                         last_p = stk->points[stk->nb_points - 1].p;
1088                 }
1089                 else if (LAST_SNAP_POINT_VALID)
1090                 {
1091                         last_p = LAST_SNAP_POINT;
1092                 }
1093
1094
1095                 for (p1 = sketch->depth_peels.first; p1; p1 = p1->next)
1096                 {
1097                         if (p1->flag == 0)
1098                         {
1099                                 float vec[3];
1100                                 float new_dist;
1101                                 float new_size = 0;
1102
1103                                 p2 = NULL;
1104                                 p1->flag = 1;
1105
1106                                 /* if peeling objects, take the first and last from each object */
1107                                 if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT)
1108                                 {
1109                                         DepthPeel *peel;
1110                                         for (peel = p1->next; peel; peel = peel->next)
1111                                         {
1112                                                 if (peel->ob == p1->ob)
1113                                                 {
1114                                                         peel->flag = 1;
1115                                                         p2 = peel;
1116                                                 }
1117                                         }
1118                                 }
1119                                 /* otherwise, pair first with second and so on */
1120                                 else
1121                                 {
1122                                         for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
1123                                         {
1124                                                 /* nothing to do here */
1125                                         }
1126                                 }
1127
1128                                 if (p2)
1129                                 {
1130                                         p2->flag = 1;
1131
1132                                         VecAddf(vec, p1->p, p2->p);
1133                                         VecMulf(vec, 0.5f);
1134                                         new_size = VecLenf(p1->p, p2->p);
1135                                 }
1136                                 else
1137                                 {
1138                                         VECCOPY(vec, p1->p);
1139                                 }
1140
1141                                 if (last_p == NULL)
1142                                 {
1143                                         VECCOPY(p, vec);
1144                                         size = new_size;
1145                                         dist = 0;
1146                                         break;
1147                                 }
1148
1149                                 new_dist = VecLenf(last_p, vec);
1150
1151                                 if (new_dist < dist)
1152                                 {
1153                                         VECCOPY(p, vec);
1154                                         dist = new_dist;
1155                                         size = new_size;
1156                                 }
1157                         }
1158                 }
1159
1160                 if (dist != FLT_MAX)
1161                 {
1162                         pt->type = dd->type;
1163                         pt->mode = PT_SNAP;
1164                         pt->size = size / 2;
1165                         VECCOPY(pt->p, p);
1166
1167                         point_added = 1;
1168                 }
1169
1170                 //BLI_freelistN(&depth_peels);
1171         }
1172         else
1173         {
1174                 SK_Stroke *snap_stk;
1175                 float vec[3];
1176                 float no[3];
1177                 int found = 0;
1178                 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
1179
1180                 /* snap to strokes */
1181                 // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
1182                 for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
1183                 {
1184                         SK_Point *spt = NULL;
1185                         if (snap_stk == stk)
1186                         {
1187                                 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
1188                         }
1189                         else
1190                         {
1191                                 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
1192                         }
1193
1194                         if (spt != NULL)
1195                         {
1196                                 VECCOPY(pt->p, spt->p);
1197                                 point_added = 1;
1198                         }
1199                 }
1200
1201                 /* try to snap to closer object */
1202                 found = snapObjectsContext(C, dd->mval, &dist, vec, no, SNAP_NOT_SELECTED);
1203                 if (found == 1)
1204                 {
1205                         pt->type = dd->type;
1206                         pt->mode = PT_SNAP;
1207                         VECCOPY(pt->p, vec);
1208
1209                         point_added = 1;
1210                 }
1211         }
1212
1213         return point_added;
1214 }
1215
1216 int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1217 {
1218         int point_added;
1219         ARegion *ar = CTX_wm_region(C);
1220         RegionView3D *rv3d = ar->regiondata;
1221         SK_Point pt;
1222
1223         sk_initPoint(&pt, dd, rv3d->viewinv[2]);
1224
1225         point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
1226
1227         if (point_added)
1228         {
1229                 float final_p[3];
1230                 float length, distance;
1231                 int total;
1232                 int i;
1233
1234                 VECCOPY(final_p, pt.p);
1235
1236                 sk_projectDrawPoint(C, pt.p, stk, dd);
1237                 sk_appendStrokePoint(stk, &pt);
1238
1239                 /* update all previous point to give smooth Z progresion */
1240                 total = 0;
1241                 length = 0;
1242                 for (i = stk->nb_points - 2; i > 0; i--)
1243                 {
1244                         length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
1245                         total++;
1246                         if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
1247                         {
1248                                 break;
1249                         }
1250                 }
1251
1252                 if (total > 1)
1253                 {
1254                         distance = sk_distanceDepth(C, final_p, stk->points[i].p);
1255
1256                         sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
1257                 }
1258
1259                 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1260
1261                 point_added = 1;
1262         }
1263
1264         return point_added;
1265 }
1266
1267 void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
1268 {
1269         ToolSettings *ts = CTX_data_tool_settings(C);
1270         int point_added = 0;
1271
1272         if (snap)
1273         {
1274                 point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
1275         }
1276
1277         if (point_added == 0)
1278         {
1279                 point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
1280         }
1281
1282         if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST)
1283         {
1284                 sk_updateOverdraw(C, sketch, stk, dd);
1285         }
1286 }
1287
1288 void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
1289 {
1290         int point_added = 0;
1291
1292         if (snap)
1293         {
1294                 point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
1295                 LAST_SNAP_POINT_VALID = 1;
1296                 VECCOPY(LAST_SNAP_POINT, pt->p);
1297         }
1298         else
1299         {
1300                 LAST_SNAP_POINT_VALID = 0;
1301         }
1302
1303         if (point_added == 0)
1304         {
1305                 point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
1306         }
1307 }
1308
1309 /********************************************/
1310
1311 static void* headPoint(void *arg);
1312 static void* tailPoint(void *arg);
1313 static void* nextPoint(void *arg);
1314 static void* nextNPoint(void *arg, int n);
1315 static void* peekPoint(void *arg, int n);
1316 static void* previousPoint(void *arg);
1317 static int   iteratorStopped(void *arg);
1318
1319 static void initIteratorFct(SK_StrokeIterator *iter)
1320 {
1321         iter->head = headPoint;
1322         iter->tail = tailPoint;
1323         iter->peek = peekPoint;
1324         iter->next = nextPoint;
1325         iter->nextN = nextNPoint;
1326         iter->previous = previousPoint;
1327         iter->stopped = iteratorStopped;
1328 }
1329
1330 static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
1331 {
1332         SK_Point *pt = NULL;
1333
1334         if (index >= 0 && index < iter->length)
1335         {
1336                 pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
1337                 iter->p = pt->p;
1338                 iter->no = pt->no;
1339                 iter->size = pt->size;
1340         }
1341         else
1342         {
1343                 iter->p = NULL;
1344                 iter->no = NULL;
1345                 iter->size = 0;
1346         }
1347
1348         return pt;
1349 }
1350
1351 void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
1352 {
1353         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1354
1355         initIteratorFct(iter);
1356         iter->stroke = stk;
1357
1358         if (start < end)
1359         {
1360                 iter->start = start + 1;
1361                 iter->end = end - 1;
1362                 iter->stride = 1;
1363         }
1364         else
1365         {
1366                 iter->start = start - 1;
1367                 iter->end = end + 1;
1368                 iter->stride = -1;
1369         }
1370
1371         iter->length = iter->stride * (iter->end - iter->start + 1);
1372
1373         iter->index = -1;
1374 }
1375
1376
1377 static void* headPoint(void *arg)
1378 {
1379         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1380         SK_Point *result = NULL;
1381
1382         result = &(iter->stroke->points[iter->start - iter->stride]);
1383         iter->p = result->p;
1384         iter->no = result->no;
1385         iter->size = result->size;
1386
1387         return result;
1388 }
1389
1390 static void* tailPoint(void *arg)
1391 {
1392         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1393         SK_Point *result = NULL;
1394
1395         result = &(iter->stroke->points[iter->end + iter->stride]);
1396         iter->p = result->p;
1397         iter->no = result->no;
1398         iter->size = result->size;
1399
1400         return result;
1401 }
1402
1403 static void* nextPoint(void *arg)
1404 {
1405         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1406         SK_Point *result = NULL;
1407
1408         iter->index++;
1409         if (iter->index < iter->length)
1410         {
1411                 result = setIteratorValues(iter, iter->index);
1412         }
1413
1414         return result;
1415 }
1416
1417 static void* nextNPoint(void *arg, int n)
1418 {
1419         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1420         SK_Point *result = NULL;
1421
1422         iter->index += n;
1423
1424         /* check if passed end */
1425         if (iter->index < iter->length)
1426         {
1427                 result = setIteratorValues(iter, iter->index);
1428         }
1429
1430         return result;
1431 }
1432
1433 static void* peekPoint(void *arg, int n)
1434 {
1435         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1436         SK_Point *result = NULL;
1437         int index = iter->index + n;
1438
1439         /* check if passed end */
1440         if (index < iter->length)
1441         {
1442                 result = setIteratorValues(iter, index);
1443         }
1444
1445         return result;
1446 }
1447
1448 static void* previousPoint(void *arg)
1449 {
1450         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1451         SK_Point *result = NULL;
1452
1453         if (iter->index > 0)
1454         {
1455                 iter->index--;
1456                 result = setIteratorValues(iter, iter->index);
1457         }
1458
1459         return result;
1460 }
1461
1462 static int iteratorStopped(void *arg)
1463 {
1464         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1465
1466         if (iter->index >= iter->length)
1467         {
1468                 return 1;
1469         }
1470         else
1471         {
1472                 return 0;
1473         }
1474 }
1475
1476 void sk_convertStroke(bContext *C, SK_Stroke *stk)
1477 {
1478         Object *obedit = CTX_data_edit_object(C);
1479         ToolSettings *ts = CTX_data_tool_settings(C);
1480         bArmature *arm = obedit->data;
1481         SK_Point *head;
1482         EditBone *parent = NULL;
1483         float invmat[4][4]; /* move in caller function */
1484         float tmat[3][3];
1485         int head_index = 0;
1486         int i;
1487
1488         head = NULL;
1489
1490         Mat4Invert(invmat, obedit->obmat);
1491
1492         Mat3CpyMat4(tmat, obedit->obmat);
1493         Mat3Transp(tmat);
1494
1495         for (i = 0; i < stk->nb_points; i++)
1496         {
1497                 SK_Point *pt = stk->points + i;
1498
1499                 if (pt->type == PT_EXACT)
1500                 {
1501                         if (head == NULL)
1502                         {
1503                                 head_index = i;
1504                                 head = pt;
1505                         }
1506                         else
1507                         {
1508                                 EditBone *bone = NULL;
1509                                 EditBone *new_parent;
1510
1511                                 if (i - head_index > 1)
1512                                 {
1513                                         SK_StrokeIterator sk_iter;
1514                                         BArcIterator *iter = (BArcIterator*)&sk_iter;
1515
1516                                         initStrokeIterator(iter, stk, head_index, i);
1517
1518                                         if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1519                                         {
1520                                                 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
1521                                         }
1522                                         else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1523                                         {
1524                                                 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
1525                                         }
1526                                         else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1527                                         {
1528                                                 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
1529                                         }
1530                                 }
1531
1532                                 if (bone == NULL)
1533                                 {
1534                                         bone = addEditBone(arm, "Bone");
1535
1536                                         VECCOPY(bone->head, head->p);
1537                                         VECCOPY(bone->tail, pt->p);
1538
1539                                         Mat4MulVecfl(invmat, bone->head);
1540                                         Mat4MulVecfl(invmat, bone->tail);
1541                                         setBoneRollFromNormal(bone, head->no, invmat, tmat);
1542                                 }
1543
1544                                 new_parent = bone;
1545                                 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
1546
1547                                 /* move to end of chain */
1548                                 while (bone->parent != NULL)
1549                                 {
1550                                         bone = bone->parent;
1551                                         bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
1552                                 }
1553
1554                                 if (parent != NULL)
1555                                 {
1556                                         bone->parent = parent;
1557                                         bone->flag |= BONE_CONNECTED;
1558                                 }
1559
1560                                 parent = new_parent;
1561                                 head_index = i;
1562                                 head = pt;
1563                         }
1564                 }
1565         }
1566 }
1567
1568 void sk_convert(bContext *C, SK_Sketch *sketch)
1569 {
1570         ToolSettings *ts = CTX_data_tool_settings(C);
1571         SK_Stroke *stk;
1572
1573         for (stk = sketch->strokes.first; stk; stk = stk->next)
1574         {
1575                 if (stk->selected == 1)
1576                 {
1577                         if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
1578                         {
1579                                 sk_retargetStroke(C, stk);
1580                         }
1581                         else
1582                         {
1583                                 sk_convertStroke(C, stk);
1584                         }
1585 //                      XXX
1586 //                      allqueue(REDRAWBUTSEDIT, 0);
1587                 }
1588         }
1589 }
1590 /******************* GESTURE *************************/
1591
1592
1593 /* returns the number of self intersections */
1594 int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
1595 {
1596         ARegion *ar = CTX_wm_region(C);
1597         int added = 0;
1598         int s_i;
1599
1600         for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
1601         {
1602                 float s_p1[3] = {0, 0, 0};
1603                 float s_p2[3] = {0, 0, 0};
1604                 int g_i;
1605
1606                 project_float(ar, gesture->points[s_i].p, s_p1);
1607                 project_float(ar, gesture->points[s_i + 1].p, s_p2);
1608
1609                 /* start checking from second next, because two consecutive cannot intersect */
1610                 for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
1611                 {
1612                         float g_p1[3] = {0, 0, 0};
1613                         float g_p2[3] = {0, 0, 0};
1614                         float vi[3];
1615                         float lambda;
1616
1617                         project_float(ar, gesture->points[g_i].p, g_p1);
1618                         project_float(ar, gesture->points[g_i + 1].p, g_p2);
1619
1620                         if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
1621                         {
1622                                 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
1623
1624                                 isect->gesture_index = g_i;
1625                                 isect->before = s_i;
1626                                 isect->after = s_i + 1;
1627                                 isect->stroke = gesture;
1628
1629                                 VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
1630                                 VecMulf(isect->p, lambda);
1631                                 VecAddf(isect->p, isect->p, gesture->points[s_i].p);
1632
1633                                 BLI_addtail(list, isect);
1634
1635                                 added++;
1636                         }
1637                 }
1638         }
1639
1640         return added;
1641 }
1642
1643 int cmpIntersections(void *i1, void *i2)
1644 {
1645         SK_Intersection *isect1 = i1, *isect2 = i2;
1646
1647         if (isect1->stroke == isect2->stroke)
1648         {
1649                 if (isect1->before < isect2->before)
1650                 {
1651                         return -1;
1652                 }
1653                 else if (isect1->before > isect2->before)
1654                 {
1655                         return 1;
1656                 }
1657                 else
1658                 {
1659                         if (isect1->lambda < isect2->lambda)
1660                         {
1661                                 return -1;
1662                         }
1663                         else if (isect1->lambda > isect2->lambda)
1664                         {
1665                                 return 1;
1666                         }
1667                 }
1668         }
1669
1670         return 0;
1671 }
1672
1673
1674 /* returns the maximum number of intersections per stroke */
1675 int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
1676 {
1677         ARegion *ar = CTX_wm_region(C);
1678         ScrArea *sa = CTX_wm_area(C);
1679         View3D *v3d = sa->spacedata.first;
1680         SK_Stroke *stk;
1681         int added = 0;
1682
1683         for (stk = sketch->strokes.first; stk; stk = stk->next)
1684         {
1685                 int s_added = 0;
1686                 int s_i;
1687
1688                 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
1689                 {
1690                         float s_p1[3] = {0, 0, 0};
1691                         float s_p2[3] = {0, 0, 0};
1692                         int g_i;
1693
1694                         project_float(ar, stk->points[s_i].p, s_p1);
1695                         project_float(ar, stk->points[s_i + 1].p, s_p2);
1696
1697                         for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
1698                         {
1699                                 float g_p1[3] = {0, 0, 0};
1700                                 float g_p2[3] = {0, 0, 0};
1701                                 float vi[3];
1702                                 float lambda;
1703
1704                                 project_float(ar, gesture->points[g_i].p, g_p1);
1705                                 project_float(ar, gesture->points[g_i + 1].p, g_p2);
1706
1707                                 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
1708                                 {
1709                                         SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
1710                                         float ray_start[3], ray_end[3];
1711                                         short mval[2];
1712
1713                                         isect->gesture_index = g_i;
1714                                         isect->before = s_i;
1715                                         isect->after = s_i + 1;
1716                                         isect->stroke = stk;
1717                                         isect->lambda = lambda;
1718
1719                                         mval[0] = (short)(vi[0]);
1720                                         mval[1] = (short)(vi[1]);
1721                                         viewline(ar, v3d, mval, ray_start, ray_end);
1722
1723                                         LineIntersectLine(      stk->points[s_i].p,
1724                                                                                 stk->points[s_i + 1].p,
1725                                                                                 ray_start,
1726                                                                                 ray_end,
1727                                                                                 isect->p,
1728                                                                                 vi);
1729
1730                                         BLI_addtail(list, isect);
1731
1732                                         s_added++;
1733                                 }
1734                         }
1735                 }
1736
1737                 added = MAX2(s_added, added);
1738         }
1739
1740         BLI_sortlist(list, cmpIntersections);
1741
1742         return added;
1743 }
1744
1745 int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
1746 {
1747         SK_StrokeIterator sk_iter;
1748         BArcIterator *iter = (BArcIterator*)&sk_iter;
1749
1750         float CORRELATION_THRESHOLD = 0.99f;
1751         float *vec;
1752         int i, j;
1753
1754         sk_appendStrokePoint(segments, &gesture->points[0]);
1755         vec = segments->points[segments->nb_points - 1].p;
1756
1757         initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
1758
1759         for (i = 1, j = 0; i < gesture->nb_points; i++)
1760         {
1761                 float n[3];
1762
1763                 /* Calculate normal */
1764                 VecSubf(n, gesture->points[i].p, vec);
1765
1766                 if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
1767                 {
1768                         j = i - 1;
1769                         sk_appendStrokePoint(segments, &gesture->points[j]);
1770                         vec = segments->points[segments->nb_points - 1].p;
1771                         segments->points[segments->nb_points - 1].type = PT_EXACT;
1772                 }
1773         }
1774
1775         sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
1776
1777         return segments->nb_points - 1;
1778 }
1779
1780 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1781 {
1782         if (gest->nb_segments == 1 && gest->nb_intersections == 1)
1783         {
1784                 return 1;
1785         }
1786
1787         return 0;
1788 }
1789
1790 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1791 {
1792         SK_Intersection *isect;
1793
1794         for (isect = gest->intersections.first; isect; isect = isect->next)
1795         {
1796                 SK_Point pt;
1797
1798                 pt.type = PT_EXACT;
1799                 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
1800                 VECCOPY(pt.p, isect->p);
1801                 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
1802
1803                 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
1804         }
1805 }
1806
1807 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1808 {
1809         if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
1810         {
1811                 float s1[3], s2[3];
1812                 float angle;
1813
1814                 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
1815                 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
1816
1817                 angle = RAD2DEG(VecAngle2(s1, s2));
1818
1819                 if (angle > 60 && angle < 120)
1820                 {
1821                         return 1;
1822                 }
1823         }
1824
1825         return 0;
1826 }
1827
1828 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1829 {
1830         SK_Intersection *isect;
1831         float trim_dir[3];
1832
1833         VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
1834
1835         for (isect = gest->intersections.first; isect; isect = isect->next)
1836         {
1837                 SK_Point pt;
1838                 float stroke_dir[3];
1839
1840                 pt.type = PT_EXACT;
1841                 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
1842                 VECCOPY(pt.p, isect->p);
1843                 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
1844
1845                 VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
1846
1847                 /* same direction, trim end */
1848                 if (Inpf(stroke_dir, trim_dir) > 0)
1849                 {
1850                         sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
1851                         sk_trimStroke(isect->stroke, 0, isect->after);
1852                 }
1853                 /* else, trim start */
1854                 else
1855                 {
1856                         sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
1857                         sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
1858                 }
1859
1860         }
1861 }
1862
1863 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1864 {
1865         if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
1866         {
1867                 SK_Intersection *isect, *self_isect;
1868
1869                 /* get the the last intersection of the first pair */
1870                 for( isect = gest->intersections.first; isect; isect = isect->next )
1871                 {
1872                         if (isect->stroke == isect->next->stroke)
1873                         {
1874                                 isect = isect->next;
1875                                 break;
1876                         }
1877                 }
1878
1879                 self_isect = gest->self_intersections.first;
1880
1881                 if (isect && isect->gesture_index < self_isect->gesture_index)
1882                 {
1883                         return 1;
1884                 }
1885         }
1886
1887         return 0;
1888 }
1889
1890 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1891 {
1892         SK_Intersection *isect;
1893         int command = 1;
1894
1895 //      XXX
1896 //      command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
1897         if(command < 1) return;
1898
1899         for (isect = gest->intersections.first; isect; isect = isect->next)
1900         {
1901                 SK_Intersection *i2;
1902
1903                 i2 = isect->next;
1904
1905                 if (i2 && i2->stroke == isect->stroke)
1906                 {
1907                         switch (command)
1908                         {
1909                                 case 1:
1910                                         sk_flattenStroke(isect->stroke, isect->before, i2->after);
1911                                         break;
1912                                 case 2:
1913                                         sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
1914                                         break;
1915                                 case 3:
1916                                         sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
1917                                         break;
1918                         }
1919
1920                         isect = i2;
1921                 }
1922         }
1923 }
1924
1925 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1926 {
1927         if (gest->nb_segments == 2 && gest->nb_intersections == 2)
1928         {
1929                 float s1[3], s2[3];
1930                 float angle;
1931
1932                 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
1933                 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
1934
1935                 angle = RAD2DEG(VecAngle2(s1, s2));
1936
1937                 if (angle > 120)
1938                 {
1939                         return 1;
1940                 }
1941         }
1942
1943         return 0;
1944 }
1945
1946 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1947 {
1948         SK_Intersection *isect;
1949
1950         for (isect = gest->intersections.first; isect; isect = isect->next)
1951         {
1952                 /* only delete strokes that are crossed twice */
1953                 if (isect->next && isect->next->stroke == isect->stroke)
1954                 {
1955                         isect = isect->next;
1956
1957                         sk_removeStroke(sketch, isect->stroke);
1958                 }
1959         }
1960 }
1961
1962 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
1963 {
1964         ARegion *ar = CTX_wm_region(C);
1965         if (gest->nb_segments > 2 && gest->nb_intersections == 2)
1966         {
1967                 short start_val[2], end_val[2];
1968                 short dist;
1969
1970                 project_short_noclip(ar, gest->stk->points[0].p, start_val);
1971                 project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
1972
1973                 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
1974
1975                 /* if gesture is a circle */
1976                 if ( dist <= 20 )
1977                 {
1978                         SK_Intersection *isect;
1979
1980                         /* check if it circled around an exact point */
1981                         for (isect = gest->intersections.first; isect; isect = isect->next)
1982                         {
1983                                 /* only delete strokes that are crossed twice */
1984                                 if (isect->next && isect->next->stroke == isect->stroke)
1985                                 {
1986                                         int start_index, end_index;
1987                                         int i;
1988
1989                                         start_index = MIN2(isect->after, isect->next->after);
1990                                         end_index = MAX2(isect->before, isect->next->before);
1991
1992                                         for (i = start_index; i <= end_index; i++)
1993                                         {
1994                                                 if (isect->stroke->points[i].type == PT_EXACT)
1995                                                 {
1996                                                         return 1; /* at least one exact point found, stop detect here */
1997                                                 }
1998                                         }
1999
2000                                         /* skip next */
2001                                         isect = isect->next;
2002                                 }
2003                         }
2004                 }
2005         }
2006
2007         return 0;
2008 }
2009
2010 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2011 {
2012         SK_Intersection *isect;
2013
2014         /* check if it circled around an exact point */
2015         for (isect = gest->intersections.first; isect; isect = isect->next)
2016         {
2017                 /* only merge strokes that are crossed twice */
2018                 if (isect->next && isect->next->stroke == isect->stroke)
2019                 {
2020                         int start_index, end_index;
2021                         int i;
2022
2023                         start_index = MIN2(isect->after, isect->next->after);
2024                         end_index = MAX2(isect->before, isect->next->before);
2025
2026                         for (i = start_index; i <= end_index; i++)
2027                         {
2028                                 /* if exact, switch to continuous */
2029                                 if (isect->stroke->points[i].type == PT_EXACT)
2030                                 {
2031                                         isect->stroke->points[i].type = PT_CONTINUOUS;
2032                                 }
2033                         }
2034
2035                         /* skip next */
2036                         isect = isect->next;
2037                 }
2038         }
2039 }
2040
2041 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2042 {
2043         if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
2044         {
2045                 SK_Intersection *isect;
2046
2047                 /* check if it circled around an exact point */
2048                 for (isect = gest->intersections.first; isect; isect = isect->next)
2049                 {
2050                         /* only delete strokes that are crossed twice */
2051                         if (isect->next && isect->next->stroke == isect->stroke)
2052                         {
2053                                 float start_v[3], end_v[3];
2054                                 float angle;
2055
2056                                 if (isect->gesture_index < isect->next->gesture_index)
2057                                 {
2058                                         VecSubf(start_v, isect->p, gest->stk->points[0].p);
2059                                         VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
2060                                 }
2061                                 else
2062                                 {
2063                                         VecSubf(start_v, isect->next->p, gest->stk->points[0].p);
2064                                         VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
2065                                 }
2066
2067                                 angle = RAD2DEG(VecAngle2(start_v, end_v));
2068
2069                                 if (angle > 120)
2070                                 {
2071                                         return 1;
2072                                 }
2073
2074                                 /* skip next */
2075                                 isect = isect->next;
2076                         }
2077                 }
2078         }
2079
2080         return 0;
2081 }
2082
2083 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2084 {
2085         SK_Intersection *isect;
2086
2087         for (isect = gest->intersections.first; isect; isect = isect->next)
2088         {
2089                 /* only reverse strokes that are crossed twice */
2090                 if (isect->next && isect->next->stroke == isect->stroke)
2091                 {
2092                         sk_reverseStroke(isect->stroke);
2093
2094                         /* skip next */
2095                         isect = isect->next;
2096                 }
2097         }
2098 }
2099
2100 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2101 {
2102         if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
2103         {
2104                 return 1;
2105         }
2106         return 0;
2107 }
2108
2109 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2110 {
2111         sk_convert(C, sketch);
2112 }
2113
2114 static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2115 {
2116         gest->intersections.first = gest->intersections.last = NULL;
2117         gest->self_intersections.first = gest->self_intersections.last = NULL;
2118
2119         gest->segments = sk_createStroke();
2120         gest->stk = sketch->gesture;
2121
2122         gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
2123         gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
2124         gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
2125 }
2126
2127 static void sk_freeGesture(SK_Gesture *gest)
2128 {
2129         sk_freeStroke(gest->segments);
2130         BLI_freelistN(&gest->intersections);
2131         BLI_freelistN(&gest->self_intersections);
2132 }
2133
2134 void sk_applyGesture(bContext *C, SK_Sketch *sketch)
2135 {
2136         SK_Gesture gest;
2137         SK_GestureAction *act;
2138
2139         sk_initGesture(C, &gest, sketch);
2140
2141         /* detect and apply */
2142         for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
2143         {
2144                 if (act->detect(C, &gest, sketch))
2145                 {
2146                         act->apply(C, &gest, sketch);
2147                         break;
2148                 }
2149         }
2150
2151         sk_freeGesture(&gest);
2152 }
2153
2154 /********************************************/
2155
2156
2157 void sk_selectStroke(bContext *C, SK_Sketch *sketch, short mval[2], int extend)
2158 {
2159         ViewContext vc;
2160         rcti rect;
2161         unsigned int buffer[MAXPICKBUF];
2162         short hits;
2163
2164         view3d_set_viewcontext(C, &vc);
2165
2166         rect.xmin= mval[0]-5;
2167         rect.xmax= mval[0]+5;
2168         rect.ymin= mval[1]-5;
2169         rect.ymax= mval[1]+5;
2170
2171         hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
2172
2173         if (hits>0)
2174         {
2175                 int besthitresult = -1;
2176
2177                 if(hits == 1) {
2178                         besthitresult = buffer[3];
2179                 }
2180                 else {
2181                         besthitresult = buffer[3];
2182                         /* loop and get best hit */
2183                 }
2184
2185                 if (besthitresult > 0)
2186                 {
2187                         SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
2188
2189                         if (extend == 0)
2190                         {
2191                                 sk_selectAllSketch(sketch, -1);
2192
2193                                 selected_stk->selected = 1;
2194                         }
2195                         else
2196                         {
2197                                 selected_stk->selected ^= 1;
2198                         }
2199
2200
2201                 }
2202         }
2203 }
2204
2205 void sk_queueRedrawSketch(SK_Sketch *sketch)
2206 {
2207         if (sketch->active_stroke != NULL)
2208         {
2209                 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2210
2211                 if (last != NULL)
2212                 {
2213 //                      XXX
2214 //                      allqueue(REDRAWVIEW3D, 0);
2215                 }
2216         }
2217 }
2218
2219 void sk_drawSketch(Scene *scene, View3D *v3d, SK_Sketch *sketch, int with_names)
2220 {
2221         ToolSettings *ts= scene->toolsettings;
2222         SK_Stroke *stk;
2223
2224         glClear(GL_DEPTH_BUFFER_BIT);
2225         glEnable(GL_DEPTH_TEST);
2226
2227         if (with_names)
2228         {
2229                 int id;
2230                 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
2231                 {
2232                         sk_drawStroke(stk, id, NULL, -1, -1);
2233                 }
2234
2235                 glLoadName(-1);
2236         }
2237         else
2238         {
2239                 float selected_rgb[3] = {1, 0, 0};
2240                 float unselected_rgb[3] = {1, 0.5, 0};
2241
2242                 for (stk = sketch->strokes.first; stk; stk = stk->next)
2243                 {
2244                         int start = -1;
2245                         int end = -1;
2246
2247                         if (sk_hasOverdraw(sketch, stk))
2248                         {
2249                                 sk_adjustIndexes(sketch, &start, &end);
2250                         }
2251
2252                         sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
2253
2254                         if (stk->selected == 1)
2255                         {
2256                                 sk_drawStrokeSubdivision(ts, stk);
2257                         }
2258                 }
2259
2260                 if (sketch->active_stroke != NULL)
2261                 {
2262                         SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2263
2264                         if (ts->bone_sketching & BONE_SKETCHING_QUICK)
2265                         {
2266                                 sk_drawStrokeSubdivision(ts, sketch->active_stroke);
2267                         }
2268
2269                         if (last != NULL)
2270                         {
2271                                 GLUquadric *quad = gluNewQuadric();
2272                                 gluQuadricNormals(quad, GLU_SMOOTH);
2273
2274                                 glPushMatrix();
2275
2276                                 glEnable(GL_BLEND);
2277                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2278
2279                                 switch (sketch->next_point.mode)
2280                                 {
2281                                         case PT_SNAP:
2282                                                 glColor3f(0, 1, 0);
2283                                                 break;
2284                                         case PT_PROJECT:
2285                                                 glColor3f(0, 0, 0);
2286                                                 break;
2287                                 }
2288
2289                                 sk_drawPoint(quad, &sketch->next_point, 0.1);
2290
2291                                 glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
2292
2293                                 sk_drawEdge(quad, last, &sketch->next_point, 0.1);
2294
2295                                 glDisable(GL_BLEND);
2296
2297                                 glPopMatrix();
2298
2299                                 gluDeleteQuadric(quad);
2300                         }
2301                 }
2302         }
2303
2304 #if 1
2305         if (sketch->depth_peels.first != NULL)
2306         {
2307                 float colors[8][3] = {
2308                                                                 {1, 0, 0},
2309                                                                 {0, 1, 0},
2310                                                                 {0, 0, 1},
2311                                                                 {1, 1, 0},
2312                                                                 {1, 0, 1},
2313                                                                 {0, 1, 1},
2314                                                                 {1, 1, 1},
2315                                                                 {0, 0, 0}
2316                                                         };
2317                 DepthPeel *p;
2318                 GLUquadric *quad = gluNewQuadric();
2319                 gluQuadricNormals(quad, GLU_SMOOTH);
2320
2321                 for (p = sketch->depth_peels.first; p; p = p->next)
2322                 {
2323                         int index = GET_INT_FROM_POINTER(p->ob);
2324                         index = (index >> 5) & 7;
2325
2326                         glColor3fv(colors[index]);
2327                         glPushMatrix();
2328                         glTranslatef(p->p[0], p->p[1], p->p[2]);
2329                         gluSphere(quad, 0.02, 8, 8);
2330                         glPopMatrix();
2331                 }
2332
2333                 gluDeleteQuadric(quad);
2334         }
2335 #endif
2336
2337         glDisable(GL_DEPTH_TEST);
2338
2339         /* only draw gesture in active area */
2340         if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
2341         {
2342                 float gesture_rgb[3] = {0, 0.5, 1};
2343                 sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
2344         }
2345 }
2346
2347 int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
2348 {
2349         ToolSettings *ts = CTX_data_tool_settings(C);
2350
2351         if (sketch->active_stroke != NULL)
2352         {
2353                 SK_Stroke *stk = sketch->active_stroke;
2354
2355                 sk_endStroke(C, sketch);
2356
2357                 if (ts->bone_sketching & BONE_SKETCHING_QUICK)
2358                 {
2359                         if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
2360                         {
2361                                 sk_retargetStroke(C, stk);
2362                         }
2363                         else
2364                         {
2365                                 sk_convertStroke(C, stk);
2366                         }
2367 //                      XXX
2368 //                      BIF_undo_push("Convert Sketch");
2369                         sk_removeStroke(sketch, stk);
2370 //                      XXX
2371 //                      allqueue(REDRAWBUTSEDIT, 0);
2372                 }
2373
2374 //              XXX
2375 //              allqueue(REDRAWVIEW3D, 0);
2376                 return 1;
2377         }
2378
2379         return 0;
2380 }
2381
2382 void sk_start_draw_stroke(SK_Sketch *sketch)
2383 {
2384         if (sketch->active_stroke == NULL)
2385         {
2386                 sk_startStroke(sketch);
2387                 sk_selectAllSketch(sketch, -1);
2388
2389                 sketch->active_stroke->selected = 1;
2390         }
2391 }
2392
2393 void sk_start_draw_gesture(SK_Sketch *sketch)
2394 {
2395         sketch->gesture = sk_createStroke();
2396 }
2397
2398 int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
2399 {
2400         if (sk_stroke_filtermval(dd))
2401         {
2402                 sk_addStrokePoint(C, sketch, stk, dd, snap);
2403                 sk_updateDrawData(dd);
2404                 sk_updateNextPoint(sketch, stk);
2405                 
2406                 return 1;
2407         }
2408
2409         return 0;
2410 }
2411
2412 static int ValidSketchViewContext(ViewContext *vc)
2413 {
2414         Object *obedit = vc->obedit;
2415         Scene *scene= vc->scene;
2416
2417         if (obedit &&
2418                 obedit->type == OB_ARMATURE &&
2419                 scene->toolsettings->bone_sketching & BONE_SKETCHING)
2420         {
2421                 return 1;
2422         }
2423         else
2424         {
2425                 return 0;
2426         }
2427 }
2428
2429 int BDR_drawSketchNames(ViewContext *vc)
2430 {
2431         if (ValidSketchViewContext(vc))
2432         {
2433                 SK_Sketch *sketch = viewcontextSketch(vc, 0);
2434                 if (sketch)
2435                 {
2436                         sk_drawSketch(vc->scene, vc->v3d, sketch, 1);
2437                         return 1;
2438                 }
2439         }
2440
2441         return 0;
2442 }
2443
2444 void BDR_drawSketch(const bContext *C)
2445 {
2446         if (ED_operator_sketch_mode(C))
2447         {
2448                 SK_Sketch *sketch = contextSketch(C, 0);
2449                 if (sketch)
2450                 {
2451                         sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), sketch, 0);
2452                 }
2453         }
2454 }
2455
2456 static int sketch_delete(bContext *C, wmOperator *op, wmEvent *event)
2457 {
2458         SK_Sketch *sketch = contextSketch(C, 0);
2459         if (sketch)
2460         {
2461                 sk_deleteSelectedStrokes(sketch);
2462 //                      allqueue(REDRAWVIEW3D, 0);
2463         }
2464         return OPERATOR_FINISHED;
2465 }
2466
2467 void BIF_sk_selectStroke(bContext *C, short mval[2], short extend)
2468 {
2469         ToolSettings *ts = CTX_data_tool_settings(C);
2470         SK_Sketch *sketch = contextSketch(C, 0);
2471
2472         if (sketch != NULL && ts->bone_sketching & BONE_SKETCHING)
2473         {
2474                 sk_selectStroke(C, sketch, mval, extend);
2475         }
2476 }
2477
2478 void BIF_convertSketch(bContext *C)
2479 {
2480         if (ED_operator_sketch_full_mode(C))
2481         {
2482                 SK_Sketch *sketch = contextSketch(C, 0);
2483                 if (sketch)
2484                 {
2485                         sk_convert(C, sketch);
2486 //                      BIF_undo_push("Convert Sketch");
2487 //                      allqueue(REDRAWVIEW3D, 0);
2488 //                      allqueue(REDRAWBUTSEDIT, 0);
2489                 }
2490         }
2491 }
2492
2493 void BIF_deleteSketch(bContext *C)
2494 {
2495         if (ED_operator_sketch_full_mode(C))
2496         {
2497                 SK_Sketch *sketch = contextSketch(C, 0);
2498                 if (sketch)
2499                 {
2500                         sk_deleteSelectedStrokes(sketch);
2501 //                      BIF_undo_push("Convert Sketch");
2502 //                      allqueue(REDRAWVIEW3D, 0);
2503                 }
2504         }
2505 }
2506
2507 #if 0
2508 void BIF_selectAllSketch(bContext *C, int mode)
2509 {
2510         if (BIF_validSketchMode(C))
2511         {
2512                 SK_Sketch *sketch = contextSketch(C, 0);
2513                 if (sketch)
2514                 {
2515                         sk_selectAllSketch(sketch, mode);
2516 //                      XXX
2517 //                      allqueue(REDRAWVIEW3D, 0);
2518                 }
2519         }
2520 }
2521 #endif
2522
2523 SK_Sketch* contextSketch(const bContext *C, int create)
2524 {
2525         Object *obedit = CTX_data_edit_object(C);
2526         SK_Sketch *sketch = NULL;
2527
2528         if (obedit && obedit->type == OB_ARMATURE)
2529         {
2530                 bArmature *arm = obedit->data;
2531         
2532                 if (arm->sketch == NULL && create)
2533                 {
2534                         arm->sketch = createSketch();
2535                 }
2536                 sketch = arm->sketch;
2537         }
2538
2539         return sketch;
2540 }
2541
2542 SK_Sketch* viewcontextSketch(ViewContext *vc, int create)
2543 {
2544         Object *obedit = vc->obedit;
2545         SK_Sketch *sketch = NULL;
2546
2547         if (obedit && obedit->type == OB_ARMATURE)
2548         {
2549                 bArmature *arm = obedit->data;
2550         
2551                 if (arm->sketch == NULL && create)
2552                 {
2553                         arm->sketch = createSketch();
2554                 }
2555                 sketch = arm->sketch;
2556         }
2557
2558         return sketch;
2559 }
2560
2561 static int sketch_cancel(bContext *C, wmOperator *op, wmEvent *event)
2562 {
2563         SK_Sketch *sketch = contextSketch(C, 0);
2564         if (sketch != NULL)
2565         {
2566                 sk_cancelStroke(sketch);
2567                 ED_area_tag_redraw(CTX_wm_area(C));
2568                 return OPERATOR_FINISHED;
2569         }
2570         return OPERATOR_PASS_THROUGH;
2571 }
2572
2573 static int sketch_finish(bContext *C, wmOperator *op, wmEvent *event)
2574 {
2575         SK_Sketch *sketch = contextSketch(C, 0);
2576         if (sketch != NULL)
2577         {
2578                 if (sk_finish_stroke(C, sketch))
2579                 {
2580                         ED_area_tag_redraw(CTX_wm_area(C));
2581                         return OPERATOR_FINISHED;
2582                 }
2583         }
2584         return OPERATOR_PASS_THROUGH;
2585 }
2586
2587 static int sketch_select(bContext *C, wmOperator *op, wmEvent *event)
2588 {
2589         SK_Sketch *sketch = contextSketch(C, 0);
2590         if (sketch)
2591         {
2592                 short extend = 0;
2593                 sk_selectStroke(C, sketch, event->mval, extend);
2594                 ED_area_tag_redraw(CTX_wm_area(C));
2595         }
2596
2597         return OPERATOR_FINISHED;
2598 }
2599
2600 static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op)
2601 {
2602         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2603         sk_cancelStroke(sketch);
2604         MEM_freeN(op->customdata);
2605         return OPERATOR_CANCELLED;
2606 }
2607
2608 static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
2609 {
2610         short snap = RNA_boolean_get(op->ptr, "snap");
2611         SK_DrawData *dd;
2612         SK_Sketch *sketch = contextSketch(C, 1);
2613
2614         op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
2615         sk_initDrawData(dd, event->mval);
2616
2617         sk_start_draw_stroke(sketch);
2618
2619         sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap);
2620
2621         WM_event_add_modal_handler(C, op);
2622
2623         return OPERATOR_RUNNING_MODAL;
2624 }
2625
2626 static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op)
2627 {
2628         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2629         sk_cancelStroke(sketch);
2630         MEM_freeN(op->customdata);
2631         return OPERATOR_CANCELLED;
2632 }
2633
2634 static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
2635 {
2636         short snap = RNA_boolean_get(op->ptr, "snap");
2637         SK_DrawData *dd;
2638         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2639         sk_cancelStroke(sketch);
2640
2641         op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
2642         sk_initDrawData(dd, event->mval);
2643
2644         sk_start_draw_gesture(sketch);
2645         sk_draw_stroke(C, sketch, sketch->gesture, dd, snap);
2646
2647         WM_event_add_modal_handler(C, op);
2648
2649         return OPERATOR_RUNNING_MODAL;
2650 }
2651
2652 static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short gesture, SK_Stroke *stk)
2653 {
2654         short snap = RNA_boolean_get(op->ptr, "snap");
2655         SK_DrawData *dd = op->customdata;
2656         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2657         int retval = OPERATOR_RUNNING_MODAL;
2658
2659         switch (event->type)
2660         {
2661         case LEFTCTRLKEY:
2662         case RIGHTCTRLKEY:
2663                 snap = event->ctrl;
2664                 RNA_boolean_set(op->ptr, "snap", snap);
2665                 break;
2666         case MOUSEMOVE:
2667                 dd->mval[0] = event->mval[0];
2668                 dd->mval[1] = event->mval[1];
2669                 sk_draw_stroke(C, sketch, stk, dd, snap);
2670                 ED_area_tag_redraw(CTX_wm_area(C));
2671                 break;
2672         case ESCKEY:
2673                 op->type->cancel(C, op);
2674                 ED_area_tag_redraw(CTX_wm_area(C));
2675                 retval = OPERATOR_CANCELLED;
2676                 break;
2677         case LEFTMOUSE:
2678                 if (event->val == KM_RELEASE)
2679                 {
2680                         if (gesture == 0)
2681                         {
2682                                 sk_endContinuousStroke(stk);
2683                                 sk_filterLastContinuousStroke(stk);
2684                                 sk_updateNextPoint(sketch, stk);
2685                                 ED_area_tag_redraw(CTX_wm_area(C));
2686                                 MEM_freeN(op->customdata);
2687                                 retval = OPERATOR_FINISHED;
2688                         }
2689                         else
2690                         {
2691                                 sk_endContinuousStroke(stk);
2692                                 sk_filterLastContinuousStroke(stk);
2693
2694                                 if (stk->nb_points > 1)
2695                                 {
2696                                         /* apply gesture here */
2697                                         sk_applyGesture(C, sketch);
2698                                 }
2699
2700                                 sk_freeStroke(stk);
2701                                 sketch->gesture = NULL;
2702
2703                                 ED_area_tag_redraw(CTX_wm_area(C));
2704                                 MEM_freeN(op->customdata);
2705                                 retval = OPERATOR_FINISHED;
2706                         }
2707                 }
2708                 break;
2709         }
2710
2711         return retval;
2712 }
2713
2714 static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
2715 {
2716         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2717         return sketch_draw_modal(C, op, event, 0, sketch->active_stroke);
2718 }
2719
2720 static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event)
2721 {
2722         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2723         return sketch_draw_modal(C, op, event, 1, sketch->gesture);
2724 }
2725
2726 static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
2727 {
2728         short snap = RNA_boolean_get(op->ptr, "snap");
2729         SK_Sketch *sketch = contextSketch(C, 0);
2730
2731         if (sketch)
2732         {
2733                 SK_DrawData dd;
2734
2735                 sk_initDrawData(&dd, event->mval);
2736                 sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, snap);
2737                 ED_area_tag_redraw(CTX_wm_area(C));
2738         }
2739
2740         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
2741 }
2742
2743 /* ============================================== Poll Functions ============================================= */
2744
2745 int ED_operator_sketch_mode_active_stroke(bContext *C)
2746 {
2747         ToolSettings *ts = CTX_data_tool_settings(C);
2748         SK_Sketch *sketch = contextSketch(C, 0);
2749
2750         if (ts->bone_sketching & BONE_SKETCHING &&
2751                 sketch != NULL &&
2752                 sketch->active_stroke != NULL)
2753         {
2754                 return 1;
2755         }
2756         else
2757         {
2758                 return 0;
2759         }
2760 }
2761
2762 int ED_operator_sketch_mode_gesture(bContext *C)
2763 {
2764         ToolSettings *ts = CTX_data_tool_settings(C);
2765         SK_Sketch *sketch = contextSketch(C, 0);
2766
2767         if (ts->bone_sketching & BONE_SKETCHING &&
2768                 (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
2769                 sketch != NULL &&
2770                 sketch->active_stroke == NULL)
2771         {
2772                 return 1;
2773         }
2774         else
2775         {
2776                 return 0;
2777         }
2778 }
2779
2780 int ED_operator_sketch_full_mode(bContext *C)
2781 {
2782         Object *obedit = CTX_data_edit_object(C);
2783         ToolSettings *ts = CTX_data_tool_settings(C);
2784
2785         if (obedit &&
2786                 obedit->type == OB_ARMATURE &&
2787                 ts->bone_sketching & BONE_SKETCHING &&
2788                 (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0)
2789         {
2790                 return 1;
2791         }
2792         else
2793         {
2794                 return 0;
2795         }
2796 }
2797
2798 int ED_operator_sketch_mode(const bContext *C)
2799 {
2800         Object *obedit = CTX_data_edit_object(C);
2801         ToolSettings *ts = CTX_data_tool_settings(C);
2802
2803         if (obedit &&
2804                 obedit->type == OB_ARMATURE &&
2805                 ts->bone_sketching & BONE_SKETCHING)
2806         {
2807                 return 1;
2808         }
2809         else
2810         {
2811                 return 0;
2812         }
2813 }
2814
2815 /* ================================================ Operators ================================================ */
2816
2817 void SKETCH_OT_delete(wmOperatorType *ot)
2818 {
2819         /* identifiers */
2820         ot->name= "delete";
2821         ot->idname= "SKETCH_OT_delete";
2822
2823         /* api callbacks */
2824         ot->invoke= sketch_delete;
2825
2826         ot->poll= ED_operator_sketch_full_mode;
2827
2828         /* flags */
2829 //      ot->flag= OPTYPE_UNDO;
2830 }
2831
2832 void SKETCH_OT_select(wmOperatorType *ot)
2833 {
2834         /* identifiers */
2835         ot->name= "select";
2836         ot->idname= "SKETCH_OT_select";
2837
2838         /* api callbacks */
2839         ot->invoke= sketch_select;
2840
2841         ot->poll= ED_operator_sketch_full_mode;
2842
2843         /* flags */
2844 //      ot->flag= OPTYPE_UNDO;
2845 }
2846
2847 void SKETCH_OT_cancel_stroke(wmOperatorType *ot)
2848 {
2849         /* identifiers */
2850         ot->name= "cancel stroke";
2851         ot->idname= "SKETCH_OT_cancel_stroke";
2852
2853         /* api callbacks */
2854         ot->invoke= sketch_cancel;
2855
2856         ot->poll= ED_operator_sketch_mode_active_stroke;
2857
2858         /* flags */
2859 //      ot->flag= OPTYPE_UNDO;
2860 }
2861
2862 void SKETCH_OT_finish_stroke(wmOperatorType *ot)
2863 {
2864         /* identifiers */
2865         ot->name= "end stroke";
2866         ot->idname= "SKETCH_OT_finish_stroke";
2867
2868         /* api callbacks */
2869         ot->invoke= sketch_finish;
2870
2871         ot->poll= ED_operator_sketch_mode_active_stroke;
2872
2873         /* flags */
2874 //      ot->flag= OPTYPE_UNDO;
2875 }
2876
2877 void SKETCH_OT_draw_preview(wmOperatorType *ot)
2878 {
2879         /* identifiers */
2880         ot->name= "draw preview";
2881         ot->idname= "SKETCH_OT_draw_preview";
2882
2883         /* api callbacks */
2884         ot->invoke= sketch_draw_preview;
2885
2886         ot->poll= ED_operator_sketch_mode_active_stroke;
2887
2888         RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
2889
2890         /* flags */
2891 //      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2892 }
2893
2894 void SKETCH_OT_draw_stroke(wmOperatorType *ot)
2895 {
2896         /* identifiers */
2897         ot->name= "draw stroke";
2898         ot->idname= "SKETCH_OT_draw_stroke";
2899
2900         /* api callbacks */
2901         ot->invoke = sketch_draw_stroke;
2902         ot->modal  = sketch_draw_stroke_modal;
2903         ot->cancel = sketch_draw_stroke_cancel;
2904
2905         ot->poll= (int (*)(bContext *))ED_operator_sketch_mode;
2906
2907         RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
2908
2909         /* flags */
2910         ot->flag= OPTYPE_BLOCKING; // OPTYPE_REGISTER|OPTYPE_UNDO
2911 }
2912
2913 void SKETCH_OT_gesture(wmOperatorType *ot)
2914 {
2915         /* identifiers */
2916         ot->name= "gesture";
2917         ot->idname= "SKETCH_OT_gesture";
2918
2919         /* api callbacks */
2920         ot->invoke = sketch_draw_gesture;
2921         ot->modal  = sketch_draw_gesture_modal;
2922         ot->cancel = sketch_draw_gesture_cancel;
2923
2924         ot->poll= ED_operator_sketch_mode_gesture;
2925
2926         RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
2927
2928         /* flags */
2929         ot->flag= OPTYPE_BLOCKING; // OPTYPE_UNDO
2930 }
2931