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