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