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