4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * ***** END GPL LICENSE BLOCK *****
26 #include "MEM_guardedalloc.h"
28 #include "DNA_listBase.h"
29 #include "DNA_scene_types.h"
30 #include "DNA_view3d_types.h"
31 #include "DNA_meshdata_types.h"
32 #include "DNA_object_types.h"
33 #include "DNA_armature_types.h"
35 #include "BLI_blenlib.h"
36 #include "BLI_arithb.h"
37 #include "BLI_graph.h"
39 #include "BKE_utildefines.h"
40 #include "BKE_global.h"
41 #include "BKE_DerivedMesh.h"
42 #include "BKE_object.h"
48 #include "BIF_resources.h"
49 #include "BIF_screen.h"
50 #include "BIF_space.h"
51 #include "BIF_mywindow.h"
52 #include "BIF_editarmature.h"
53 #include "BIF_sketch.h"
54 #include "BIF_retarget.h"
73 typedef struct SK_Point
81 typedef struct SK_Stroke
83 struct SK_Stroke *next, *prev;
91 #define SK_Stroke_BUFFER_INIT_SIZE 20
93 typedef struct SK_DrawData
96 short previous_mval[2];
100 typedef struct SK_Intersection
102 struct SK_Intersection *next, *prev;
110 typedef struct SK_Sketch
113 SK_Stroke *active_stroke;
118 SK_Sketch *GLOBAL_sketch = NULL;
121 #define SNAP_MIN_DISTANCE 12
123 /******************** PROTOTYPES ******************************/
125 typedef int(NextSubdivisionFunc)(SK_Stroke*, int, int, float[3], float[3]);
127 void sk_deleteSelectedStrokes(SK_Sketch *sketch);
129 void sk_freeStroke(SK_Stroke *stk);
130 void sk_freeSketch(SK_Sketch *sketch);
132 SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
134 int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]);
135 int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]);
136 int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3]);
138 /******************** PEELING *********************************/
140 typedef struct SK_DepthPeel
142 struct SK_DepthPeel *next, *prev;
151 int cmpPeel(void *arg1, void *arg2)
153 SK_DepthPeel *p1 = arg1;
154 SK_DepthPeel *p2 = arg2;
157 if (p1->depth < p2->depth)
161 else if (p1->depth > p2->depth)
169 void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob)
171 SK_DepthPeel *peel = MEM_callocN(sizeof(SK_DepthPeel), "DepthPeel");
176 VECCOPY(peel->no, no);
178 BLI_addtail(depth_peels, peel);
183 int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels)
186 int totvert = dm->getNumVerts(dm);
187 int totface = dm->getNumFaces(dm);
191 float timat[3][3]; /* transpose inverse matrix for normals */
192 float ray_start_local[3], ray_normal_local[3];
195 Mat4Invert(imat, obmat);
197 Mat3CpyMat4(timat, imat);
200 VECCOPY(ray_start_local, ray_start);
201 VECCOPY(ray_normal_local, ray_normal);
203 Mat4MulVecfl(imat, ray_start_local);
204 Mat4Mul3Vecfl(imat, ray_normal_local);
207 /* If number of vert is more than an arbitrary limit,
208 * test against boundbox first
211 struct BoundBox *bb = object_get_boundbox(ob);
212 test = ray_hit_boundbox(bb, ray_start_local, ray_normal_local);
216 MVert *verts = dm->getVertArray(dm);
217 MFace *faces = dm->getFaceArray(dm);
220 for( i = 0; i < totface; i++) {
221 MFace *f = faces + i;
226 result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, &lambda, NULL);
229 float location[3], normal[3];
233 VECCOPY(intersect, ray_normal_local);
234 VecMulf(intersect, lambda);
235 VecAddf(intersect, intersect, ray_start_local);
237 VECCOPY(location, intersect);
240 CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
242 CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
244 Mat4MulVecfl(obmat, location);
246 new_depth = VecLenf(location, ray_start);
248 Mat3MulVecfl(timat, normal);
251 addDepthPeel(depth_peels, new_depth, location, normal, ob);
254 if (f->v4 && result == 0)
256 result = RayIntersectsTriangle(ray_start_local, ray_normal_local, verts[f->v3].co, verts[f->v4].co, verts[f->v1].co, &lambda, NULL);
259 float location[3], normal[3];
263 VECCOPY(intersect, ray_normal_local);
264 VecMulf(intersect, lambda);
265 VecAddf(intersect, intersect, ray_start_local);
267 VECCOPY(location, intersect);
270 CalcNormFloat4(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, verts[f->v4].co, normal);
272 CalcNormFloat(verts[f->v1].co, verts[f->v2].co, verts[f->v3].co, normal);
274 Mat4MulVecfl(obmat, location);
276 new_depth = VecLenf(location, ray_start);
278 Mat3MulVecfl(timat, normal);
281 addDepthPeel(depth_peels, new_depth, location, normal, ob);
291 int peelObjects(ListBase *depth_peels, short mval[2])
295 float ray_start[3], ray_normal[3];
297 viewray(mval, ray_start, ray_normal);
300 for ( base = FIRSTBASE; base != NULL; base = base->next ) {
301 if ( BASE_SELECTABLE(base) ) {
302 Object *ob = base->object;
304 if (ob->transflag & OB_DUPLI)
306 DupliObject *dupli_ob;
307 ListBase *lb = object_duplilist(G.scene, ob);
309 for(dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next)
311 Object *ob = dupli_ob->ob;
313 if (ob->type == OB_MESH) {
314 DerivedMesh *dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
317 val = peelDerivedMesh(ob, dm, dupli_ob->mat, ray_start, ray_normal, mval, depth_peels);
319 retval = retval || val;
325 free_object_duplilist(lb);
328 if (ob->type == OB_MESH) {
329 DerivedMesh *dm = NULL;
334 dm = mesh_get_derived_final(ob, CD_MASK_BAREMESH);
336 val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
340 dm = editmesh_get_derived_cage(CD_MASK_BAREMESH);
342 val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels);
345 retval = retval || val;
352 BLI_sortlist(depth_peels, cmpPeel);
356 /*********************** CONVERSION ***************************/
358 ReebNode *pointToNode(SK_Point *pt)
362 node = MEM_callocN(sizeof(ReebNode), "reeb node");
363 VECCOPY(node->p, pt->p);
368 ReebArc *strokeToArc(SK_Stroke *stk)
373 arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
374 arc->head = pointToNode(stk->points);
375 arc->tail = pointToNode(sk_lastStrokePoint(stk));
377 arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
378 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
380 for (i = 0; i < arc->bcount; i++)
382 VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
383 arc->buckets[i].no = stk->points[i + 1].no;
389 void retargetStroke(SK_Stroke *stk)
391 ReebArc *arc = strokeToArc(stk);
393 BIF_retargetArc(arc);
395 MEM_freeN(arc->head);
396 MEM_freeN(arc->tail);
397 REEB_freeArc((BArc*)arc);
400 /**************************************************************/
402 void sk_freeSketch(SK_Sketch *sketch)
404 SK_Stroke *stk, *next;
406 for (stk = sketch->strokes.first; stk; stk = next)
416 SK_Sketch* sk_createSketch()
420 sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
422 sketch->active_stroke = NULL;
423 sketch->gesture = NULL;
425 sketch->strokes.first = NULL;
426 sketch->strokes.last = NULL;
431 void sk_initPoint(SK_Point *pt)
433 VECCOPY(pt->no, G.vd->viewinv[2]);
435 /* more init code here */
438 void sk_copyPoint(SK_Point *dst, SK_Point *src)
440 memcpy(dst, src, sizeof(SK_Point));
443 void sk_allocStrokeBuffer(SK_Stroke *stk)
445 stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
448 void sk_freeStroke(SK_Stroke *stk)
450 MEM_freeN(stk->points);
454 SK_Stroke* sk_createStroke()
458 stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
462 stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
464 sk_allocStrokeBuffer(stk);
469 void sk_shrinkStrokeBuffer(SK_Stroke *stk)
471 if (stk->nb_points < stk->buf_size)
473 SK_Point *old_points = stk->points;
475 stk->buf_size = stk->nb_points;
477 sk_allocStrokeBuffer(stk);
479 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
481 MEM_freeN(old_points);
485 void sk_growStrokeBuffer(SK_Stroke *stk)
487 if (stk->nb_points == stk->buf_size)
489 SK_Point *old_points = stk->points;
493 sk_allocStrokeBuffer(stk);
495 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
497 MEM_freeN(old_points);
501 void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
503 memcpy(stk->points + n, pt, sizeof(SK_Point));
506 void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
508 int size = stk->nb_points - n;
510 sk_growStrokeBuffer(stk);
512 memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
514 memcpy(stk->points + n, pt, sizeof(SK_Point));
519 void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
521 sk_growStrokeBuffer(stk);
523 memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
528 void sk_trimStroke(SK_Stroke *stk, int start, int end)
530 int size = end - start + 1;
534 memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
537 stk->nb_points = size;
540 void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
542 if (sketch->active_stroke == stk)
544 sketch->active_stroke = NULL;
547 BLI_remlink(&sketch->strokes, stk);
551 void sk_reverseStroke(SK_Stroke *stk)
553 SK_Point *old_points = stk->points;
556 sk_allocStrokeBuffer(stk);
558 for (i = 0; i < stk->nb_points; i++)
560 sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
563 MEM_freeN(old_points);
567 void sk_cancelStroke(SK_Sketch *sketch)
569 if (sketch->active_stroke != NULL)
571 sk_removeStroke(sketch, sketch->active_stroke);
575 /* Apply reverse Chaikin filter to simplify the polyline
577 void sk_filterStroke(SK_Stroke *stk, int start, int end)
579 SK_Point *old_points = stk->points;
580 int nb_points = stk->nb_points;
586 end = stk->nb_points - 1;
589 sk_allocStrokeBuffer(stk);
592 /* adding points before range */
593 for (i = 0; i < start; i++)
595 sk_appendStrokePoint(stk, old_points + i);
598 for (i = start, j = start; i <= end; i++)
605 sk_copyPoint(&pt, &old_points[j+1]);
611 VECCOPY(vec, old_points[j].p);
613 VecAddf(pt.p, pt.p, vec);
615 VECCOPY(vec, old_points[j+1].p);
617 VecAddf(pt.p, pt.p, vec);
619 VECCOPY(vec, old_points[j+2].p);
621 VecAddf(pt.p, pt.p, vec);
623 VECCOPY(vec, old_points[j+3].p);
625 VecAddf(pt.p, pt.p, vec);
627 sk_appendStrokePoint(stk, &pt);
632 /* this might be uneeded when filtering last continuous stroke */
633 if (old_points[i].type == PT_EXACT)
635 sk_appendStrokePoint(stk, old_points + i);
640 /* adding points after range */
641 for (i = end + 1; i < nb_points; i++)
643 sk_appendStrokePoint(stk, old_points + i);
646 MEM_freeN(old_points);
648 sk_shrinkStrokeBuffer(stk);
651 void sk_filterLastContinuousStroke(SK_Stroke *stk)
655 end = stk->nb_points -1;
657 for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
659 /* nothing to do here*/
664 sk_filterStroke(stk, start, end);
668 SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
672 if (stk->nb_points > 0)
674 pt = stk->points + (stk->nb_points - 1);
680 void sk_drawStroke(SK_Stroke *stk, int id, float color[3])
689 glBegin(GL_LINE_STRIP);
691 for (i = 0; i < stk->nb_points; i++)
693 glVertex3fv(stk->points[i].p);
701 float d_rgb[3] = {1, 1, 1};
704 VecSubf(d_rgb, d_rgb, rgb);
705 VecMulf(d_rgb, 1.0f / (float)stk->nb_points);
707 glBegin(GL_LINE_STRIP);
709 for (i = 0; i < stk->nb_points; i++)
712 glVertex3fv(stk->points[i].p);
713 VecAddf(rgb, rgb, d_rgb);
721 for (i = 0; i < stk->nb_points; i++)
723 if (stk->points[i].type == PT_EXACT)
725 glVertex3fv(stk->points[i].p);
732 // glColor3f(1, 1, 1);
733 // glBegin(GL_POINTS);
735 // for (i = 0; i < stk->nb_points; i++)
737 // if (stk->points[i].type == PT_CONTINUOUS)
739 // glVertex3fv(stk->points[i].p);
746 void drawSubdividedStrokeBy(SK_Stroke *stk, int start, int end, NextSubdivisionFunc next_subdividion)
748 float head[3], tail[3];
749 int bone_start = start;
752 VECCOPY(head, stk->points[start].p);
757 index = next_subdividion(stk, bone_start, end, head, tail);
763 bone_start = index; // start next bone from current index
765 index = next_subdividion(stk, bone_start, end, head, tail);
771 void sk_drawStrokeSubdivision(SK_Stroke *stk)
776 if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
782 for (i = 0; i < stk->nb_points; i++)
784 SK_Point *pt = stk->points + i;
786 if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
788 if (head_index == -1)
794 if (i - head_index > 1)
796 if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION)
798 drawSubdividedStrokeBy(stk, head_index, i, nextCorrelationSubdivision);
800 else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
802 drawSubdividedStrokeBy(stk, head_index, i, nextLengthSubdivision);
804 else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
806 drawSubdividedStrokeBy(stk, head_index, i, nextFixedSubdivision);
817 SK_Point *sk_snapPointStroke(SK_Stroke *stk, short mval[2], int *dist)
822 for (i = 0; i < stk->nb_points; i++)
824 if (stk->points[i].type == PT_EXACT)
829 project_short_noclip(stk->points[i].p, pval);
831 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
836 pt = stk->points + i;
844 SK_Point *sk_snapPointArmature(Object *ob, ListBase *ebones, short mval[2], int *dist)
849 for (bone = ebones->first; bone; bone = bone->next)
855 if ((bone->flag & BONE_CONNECTED) == 0)
857 VECCOPY(vec, bone->head);
858 Mat4MulVecfl(ob->obmat, vec);
859 project_short_noclip(vec, pval);
861 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
873 VECCOPY(vec, bone->tail);
874 Mat4MulVecfl(ob->obmat, vec);
875 project_short_noclip(vec, pval);
877 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
891 void sk_startStroke(SK_Sketch *sketch)
893 SK_Stroke *stk = sk_createStroke();
895 BLI_addtail(&sketch->strokes, stk);
896 sketch->active_stroke = stk;
899 void sk_endStroke(SK_Sketch *sketch)
901 sk_shrinkStrokeBuffer(sketch->active_stroke);
902 sketch->active_stroke = NULL;
905 void sk_updateDrawData(SK_DrawData *dd)
907 dd->type = PT_CONTINUOUS;
909 dd->previous_mval[0] = dd->mval[0];
910 dd->previous_mval[1] = dd->mval[1];
913 float sk_distanceDepth(float p1[3], float p2[3])
918 VecSubf(vec, p1, p2);
920 Projf(vec, vec, G.vd->viewinv[2]);
922 distance = VecLength(vec);
924 if (Inpf(G.vd->viewinv[2], vec) > 0)
932 void sk_interpolateDepth(SK_Stroke *stk, int start, int end, float length, float distance)
937 progress = VecLenf(stk->points[start].p, stk->points[start - 1].p);
939 for (i = start; i <= end; i++)
941 float ray_start[3], ray_normal[3];
942 float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p);
945 project_short_noclip(stk->points[i].p, pval);
946 viewray(pval, ray_start, ray_normal);
948 VecMulf(ray_normal, distance * progress / length);
949 VecAddf(stk->points[i].p, stk->points[i].p, ray_normal);
955 void sk_projectDrawPoint(float vec[3], SK_Stroke *stk, SK_DrawData *dd)
957 /* copied from grease pencil, need fixing */
958 SK_Point *last = sk_lastStrokePoint(stk);
960 //float *fp = give_cursor();
961 float fp[3] = {0, 0, 0};
966 VECCOPY(fp, last->p);
969 initgrabz(fp[0], fp[1], fp[2]);
971 /* method taken from editview.c - mouse_cursor() */
972 project_short_noclip(fp, cval);
973 window_to_3d(dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
974 VecSubf(vec, fp, dvec);
977 int sk_getStrokeDrawPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
980 pt->mode = PT_PROJECT;
981 sk_projectDrawPoint(pt->p, stk, dd);
986 int sk_addStrokeDrawPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
992 sk_getStrokeDrawPoint(&pt, sketch, stk, dd);
994 sk_appendStrokePoint(stk, &pt);
1000 int sk_getStrokeSnapPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *source_stk, SK_DrawData *dd)
1003 int dist = SNAP_MIN_DISTANCE;
1004 int point_added = 0;
1006 for (stk = sketch->strokes.first; stk; stk = stk->next)
1008 SK_Point *spt = sk_snapPointStroke(stk, dd->mval, &dist);
1012 VECCOPY(pt->p, spt->p);
1017 /* check on bones */
1019 SK_Point *spt = sk_snapPointArmature(G.obedit, &G.edbo, dd->mval, &dist);
1023 VECCOPY(pt->p, spt->p);
1030 pt->type = PT_EXACT;
1037 int sk_addStrokeSnapPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1039 int point_added = 0;
1044 point_added = sk_getStrokeSnapPoint(&pt, sketch, stk, dd);
1053 VECCOPY(final_p, pt.p);
1055 sk_projectDrawPoint(pt.p, stk, dd);
1056 sk_appendStrokePoint(stk, &pt);
1058 /* update all previous point to give smooth Z progresion */
1061 for (i = stk->nb_points - 2; i > 0; i--)
1063 length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
1065 if (stk->points[i].type == PT_EXACT)
1073 distance = sk_distanceDepth(final_p, stk->points[i].p);
1075 sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance);
1078 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1084 int sk_getStrokeEmbedPoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1086 ListBase depth_peels;
1087 SK_DepthPeel *p1, *p2;
1088 SK_Point *last_pt = NULL;
1089 float dist = FLT_MAX;
1091 int point_added = 0;
1093 depth_peels.first = depth_peels.last = NULL;
1095 peelObjects(&depth_peels, dd->mval);
1097 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
1099 last_pt = stk->points + (stk->nb_points - 1);
1103 for (p1 = depth_peels.first; p1; p1 = p1->next)
1112 for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
1114 /* nothing to do here */
1122 VecAddf(vec, p1->p, p2->p);
1127 VECCOPY(vec, p1->p);
1130 if (last_pt == NULL)
1137 new_dist = VecLenf(last_pt->p, vec);
1139 if (new_dist < dist)
1147 if (dist != FLT_MAX)
1149 pt->type = dd->type;
1150 pt->mode = PT_EMBED;
1156 BLI_freelistN(&depth_peels);
1161 int sk_addStrokeEmbedPoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1168 point_added = sk_getStrokeEmbedPoint(&pt, sketch, stk, dd);
1173 float length, distance;
1177 VECCOPY(final_p, pt.p);
1179 sk_projectDrawPoint(pt.p, stk, dd);
1180 sk_appendStrokePoint(stk, &pt);
1182 /* update all previous point to give smooth Z progresion */
1185 for (i = stk->nb_points - 2; i > 0; i--)
1187 length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
1189 if (stk->points[i].mode == PT_EMBED || stk->points[i].type == PT_EXACT)
1197 distance = sk_distanceDepth(final_p, stk->points[i].p);
1199 sk_interpolateDepth(stk, i + 1, stk->nb_points - 2, length, distance);
1202 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1210 void sk_addStrokePoint(SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
1212 int point_added = 0;
1214 if (qual & LR_CTRLKEY)
1216 point_added = sk_addStrokeSnapPoint(sketch, stk, dd);
1219 if (point_added == 0 && qual & LR_SHIFTKEY)
1221 point_added = sk_addStrokeEmbedPoint(sketch, stk, dd);
1224 if (point_added == 0)
1226 point_added = sk_addStrokeDrawPoint(sketch, stk, dd);
1230 void sk_getStrokePoint(SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
1232 int point_added = 0;
1234 if (qual & LR_CTRLKEY)
1236 point_added = sk_getStrokeSnapPoint(pt, sketch, stk, dd);
1239 if (point_added == 0 && qual & LR_SHIFTKEY)
1241 point_added = sk_getStrokeEmbedPoint(pt, sketch, stk, dd);
1244 if (point_added == 0)
1246 point_added = sk_getStrokeDrawPoint(pt, sketch, stk, dd);
1250 void sk_endContinuousStroke(SK_Stroke *stk)
1252 stk->points[stk->nb_points - 1].type = PT_EXACT;
1255 void sk_updateNextPoint(SK_Sketch *sketch)
1257 if (sketch->active_stroke)
1259 SK_Stroke *stk = sketch->active_stroke;
1260 memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
1264 int sk_stroke_filtermval(SK_DrawData *dd)
1267 if (dd->mval[0] != dd->previous_mval[0] || dd->mval[1] != dd->previous_mval[1])
1275 void sk_initDrawData(SK_DrawData *dd)
1277 getmouseco_areawin(dd->mval);
1278 dd->previous_mval[0] = -1;
1279 dd->previous_mval[1] = -1;
1280 dd->type = PT_EXACT;
1282 /********************************************/
1284 /* bone is assumed to be in GLOBAL space */
1285 void setBoneRollFromPoint(EditBone *bone, SK_Point *pt, float invmat[][4], float tmat[][3])
1287 float tangent[3], cotangent[3], normal[3];
1289 VecSubf(tangent, bone->tail, bone->head);
1290 Crossf(cotangent, tangent, pt->no);
1291 Crossf(normal, cotangent, tangent);
1293 Mat3MulVecfl(tmat, normal);
1296 bone->roll = rollBoneToVector(bone, normal);
1300 float calcStrokeCorrelation(SK_Stroke *stk, int start, int end, float v0[3], float n[3])
1302 int len = 2 + abs(end - start);
1311 /* First pass, calculate average */
1312 for (i = start; i <= end; i++)
1316 VecSubf(v, stk->points[i].p, v0);
1317 avg_t += Inpf(v, n);
1320 avg_t /= Inpf(n, n);
1321 avg_t += 1.0f; /* adding start (0) and end (1) values */
1324 /* Second pass, calculate s_xyz and s_t */
1325 for (i = start; i <= end; i++)
1330 VecSubf(v, stk->points[i].p, v0);
1334 dt = VecLength(d) - avg_t;
1337 s_xyz += Inpf(v, v);
1340 /* adding start(0) and end(1) values to s_t */
1341 s_t += (avg_t * avg_t) + (1 - avg_t) * (1 - avg_t);
1343 return 1.0f - s_xyz / s_t;
1351 int nextFixedSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
1353 static float stroke_length = 0;
1354 static float current_length;
1356 float length_threshold;
1359 if (stroke_length == 0)
1362 for (i = start + 1; i <= end; i++)
1364 stroke_length += VecLenf(stk->points[i].p, stk->points[i - 1].p);
1373 length_threshold = n * stroke_length / G.scene->toolsettings->skgen_subdivision_number;
1375 /* < and not <= because we don't care about end, it is P_EXACT anyway */
1376 for (i = start + 1; i < end; i++)
1378 current_length += VecLenf(stk->points[i].p, stk->points[i - 1].p);
1380 if (current_length >= length_threshold)
1382 VECCOPY(p, stk->points[i].p);
1391 int nextCorrelationSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
1393 float correlation_threshold = G.scene->toolsettings->skgen_correlation_limit;
1397 for (i = start + 2; i <= end; i++)
1399 /* Calculate normal */
1400 VecSubf(n, stk->points[i].p, head);
1402 if (calcStrokeCorrelation(stk, start, i, stk->points[start].p, n) < correlation_threshold)
1404 VECCOPY(p, stk->points[i - 1].p);
1412 int nextLengthSubdivision(SK_Stroke *stk, int start, int end, float head[3], float p[3])
1414 float lengthLimit = G.scene->toolsettings->skgen_length_limit;
1421 float *vec0 = stk->points[i - 1].p;
1422 float *vec1 = stk->points[i].p;
1424 /* If lengthLimit hits the current segment */
1425 if (VecLenf(vec1, head) > lengthLimit)
1429 float dv[3], off[3];
1432 /* Solve quadratic distance equation */
1433 VecSubf(dv, vec1, vec0);
1436 VecSubf(off, vec0, head);
1437 b = 2 * Inpf(dv, off);
1439 c = Inpf(off, off) - (lengthLimit * lengthLimit);
1441 f = (-b + (float)sqrt(b * b - 4 * a * c)) / (2 * a);
1443 //printf("a %f, b %f, c %f, f %f\n", a, b, c, f);
1445 if (isnan(f) == 0 && f < 1.0f)
1449 VecAddf(p, p, vec0);
1460 VecSubf(dv, vec1, vec0);
1464 VecMulf(p, lengthLimit);
1465 VecAddf(p, p, head);
1468 return i - 1; /* restart at lower bound */
1473 same = 0; // Reset same
1480 EditBone * subdivideStrokeBy(SK_Stroke *stk, int start, int end, float invmat[][4], float tmat[][3], NextSubdivisionFunc next_subdividion)
1482 bArmature *arm = G.obedit->data;
1483 EditBone *lastBone = NULL;
1484 EditBone *child = NULL;
1485 EditBone *parent = NULL;
1486 int bone_start = start;
1489 parent = addEditBone("Bone", &G.edbo, arm);
1490 VECCOPY(parent->head, stk->points[start].p);
1492 index = next_subdividion(stk, bone_start, end, parent->head, parent->tail);
1495 setBoneRollFromPoint(parent, &stk->points[index], invmat, tmat);
1496 Mat4MulVecfl(invmat, parent->head); /* going to next bone, fix previous head */
1498 child = addEditBone("Bone", &G.edbo, arm);
1499 VECCOPY(child->head, parent->tail);
1500 child->parent = parent;
1501 child->flag |= BONE_CONNECTED;
1503 parent = child; // new child is next parent
1504 bone_start = index; // start next bone from current index
1506 index = next_subdividion(stk, bone_start, end, parent->head, parent->tail);
1509 VECCOPY(parent->tail, stk->points[end].p);
1511 setBoneRollFromPoint(parent, &stk->points[end], invmat, tmat);
1513 Mat4MulVecfl(invmat, parent->head);
1514 Mat4MulVecfl(invmat, parent->tail);
1521 void sk_convertStroke(SK_Stroke *stk)
1523 bArmature *arm= G.obedit->data;
1525 EditBone *parent = NULL;
1526 float invmat[4][4]; /* move in caller function */
1533 Mat4Invert(invmat, G.obedit->obmat);
1535 Mat3CpyMat4(tmat, G.obedit->obmat);
1538 for (i = 0; i < stk->nb_points; i++)
1540 SK_Point *pt = stk->points + i;
1542 if (pt->type == PT_EXACT)
1551 EditBone *bone = NULL;
1552 EditBone *new_parent;
1554 if (i - head_index > 1)
1556 if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_CORRELATION)
1558 bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextCorrelationSubdivision);
1560 else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1562 bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextLengthSubdivision);
1564 else if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1566 bone = subdivideStrokeBy(stk, head_index, i, invmat, tmat, nextFixedSubdivision);
1572 bone = addEditBone("Bone", &G.edbo, arm);
1574 VECCOPY(bone->head, head->p);
1575 VECCOPY(bone->tail, pt->p);
1576 setBoneRollFromPoint(bone, pt, invmat, tmat);
1578 Mat4MulVecfl(invmat, bone->head);
1579 Mat4MulVecfl(invmat, bone->tail);
1583 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
1585 /* move to end of chain */
1586 while (bone->parent != NULL)
1588 bone = bone->parent;
1589 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
1594 bone->parent = parent;
1595 bone->flag |= BONE_CONNECTED;
1598 parent = new_parent;
1606 void sk_convert(SK_Sketch *sketch)
1610 for (stk = sketch->strokes.first; stk; stk = stk->next)
1612 if (stk->selected == 1)
1614 sk_convertStroke(stk);
1618 /******************* GESTURE *************************/
1621 /* returns the number of self intersections */
1622 int sk_getSelfIntersections(ListBase *list, SK_Stroke *gesture)
1627 for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
1629 float s_p1[3] = {0, 0, 0};
1630 float s_p2[3] = {0, 0, 0};
1633 project_float(gesture->points[s_i].p, s_p1);
1634 project_float(gesture->points[s_i + 1].p, s_p2);
1636 /* start checking from second next, because two consecutive cannot intersect */
1637 for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
1639 float g_p1[3] = {0, 0, 0};
1640 float g_p2[3] = {0, 0, 0};
1644 project_float(gesture->points[g_i].p, g_p1);
1645 project_float(gesture->points[g_i + 1].p, g_p2);
1647 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
1649 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
1651 isect->gesture_index = g_i;
1652 isect->before = s_i;
1653 isect->after = s_i + 1;
1654 isect->stroke = gesture;
1656 VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
1657 VecMulf(isect->p, lambda);
1658 VecAddf(isect->p, isect->p, gesture->points[s_i].p);
1660 BLI_addtail(list, isect);
1671 /* returns the maximum number of intersections per stroke */
1672 int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
1677 for (stk = sketch->strokes.first; stk; stk = stk->next)
1682 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
1684 float s_p1[3] = {0, 0, 0};
1685 float s_p2[3] = {0, 0, 0};
1688 project_float(stk->points[s_i].p, s_p1);
1689 project_float(stk->points[s_i + 1].p, s_p2);
1691 for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
1693 float g_p1[3] = {0, 0, 0};
1694 float g_p2[3] = {0, 0, 0};
1698 project_float(gesture->points[g_i].p, g_p1);
1699 project_float(gesture->points[g_i + 1].p, g_p2);
1701 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
1703 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
1704 float ray_start[3], ray_end[3];
1707 isect->gesture_index = g_i;
1708 isect->before = s_i;
1709 isect->after = s_i + 1;
1710 isect->stroke = stk;
1712 mval[0] = (short)(vi[0]);
1713 mval[1] = (short)(vi[1]);
1714 viewline(mval, ray_start, ray_end);
1716 LineIntersectLine( stk->points[s_i].p,
1717 stk->points[s_i + 1].p,
1723 BLI_addtail(list, isect);
1730 added = MAX2(s_added, added);
1737 int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
1739 float CORRELATION_THRESHOLD = 0.99f;
1743 sk_appendStrokePoint(segments, &gesture->points[0]);
1744 vec = segments->points[segments->nb_points - 1].p;
1746 for (i = 1, j = 0; i < gesture->nb_points; i++)
1750 /* Calculate normal */
1751 VecSubf(n, gesture->points[i].p, vec);
1753 if (calcStrokeCorrelation(gesture, j, i, vec, n) < CORRELATION_THRESHOLD)
1756 sk_appendStrokePoint(segments, &gesture->points[j]);
1757 vec = segments->points[segments->nb_points - 1].p;
1758 segments->points[segments->nb_points - 1].type = PT_EXACT;
1762 sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
1764 return segments->nb_points - 1;
1767 void sk_applyCutGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1769 SK_Intersection *isect;
1771 for (isect = list->first; isect; isect = isect->next)
1776 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
1777 VECCOPY(pt.p, isect->p);
1779 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
1783 int sk_detectTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1788 VecSubf(s1, segments->points[1].p, segments->points[0].p);
1789 VecSubf(s2, segments->points[2].p, segments->points[1].p);
1791 angle = VecAngle2(s1, s2);
1793 if (angle > 60 && angle < 120)
1803 void sk_applyTrimGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1805 SK_Intersection *isect;
1808 VecSubf(trim_dir, segments->points[2].p, segments->points[1].p);
1810 for (isect = list->first; isect; isect = isect->next)
1813 float stroke_dir[3];
1816 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
1817 VECCOPY(pt.p, isect->p);
1819 VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
1821 /* same direction, trim end */
1822 if (Inpf(stroke_dir, trim_dir) > 0)
1824 sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
1825 sk_trimStroke(isect->stroke, 0, isect->after);
1827 /* else, trim start */
1830 sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
1831 sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
1837 int sk_detectDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1842 VecSubf(s1, segments->points[1].p, segments->points[0].p);
1843 VecSubf(s2, segments->points[2].p, segments->points[1].p);
1845 angle = VecAngle2(s1, s2);
1857 void sk_applyDeleteGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1859 SK_Intersection *isect;
1861 for (isect = list->first; isect; isect = isect->next)
1863 /* only delete strokes that are crossed twice */
1864 if (isect->next && isect->next->stroke == isect->stroke)
1866 isect = isect->next;
1868 sk_removeStroke(sketch, isect->stroke);
1873 int sk_detectMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1875 short start_val[2], end_val[2];
1878 project_short_noclip(gesture->points[0].p, start_val);
1879 project_short_noclip(gesture->points[gesture->nb_points - 1].p, end_val);
1881 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
1883 /* if gesture is a circle */
1886 SK_Intersection *isect;
1888 /* check if it circled around an exact point */
1889 for (isect = list->first; isect; isect = isect->next)
1891 /* only delete strokes that are crossed twice */
1892 if (isect->next && isect->next->stroke == isect->stroke)
1894 int start_index, end_index;
1897 start_index = MIN2(isect->after, isect->next->after);
1898 end_index = MAX2(isect->before, isect->next->before);
1900 for (i = start_index; i <= end_index; i++)
1902 if (isect->stroke->points[i].type == PT_EXACT)
1904 return 1; /* at least one exact point found, stop detect here */
1909 isect = isect->next;
1921 void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1923 SK_Intersection *isect;
1925 /* check if it circled around an exact point */
1926 for (isect = list->first; isect; isect = isect->next)
1928 /* only merge strokes that are crossed twice */
1929 if (isect->next && isect->next->stroke == isect->stroke)
1931 int start_index, end_index;
1934 start_index = MIN2(isect->after, isect->next->after);
1935 end_index = MAX2(isect->before, isect->next->before);
1937 for (i = start_index; i <= end_index; i++)
1939 /* if exact, switch to continuous */
1940 if (isect->stroke->points[i].type == PT_EXACT)
1942 isect->stroke->points[i].type = PT_CONTINUOUS;
1947 isect = isect->next;
1952 int sk_detectReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1954 SK_Intersection *isect;
1956 /* check if it circled around an exact point */
1957 for (isect = list->first; isect; isect = isect->next)
1959 /* only delete strokes that are crossed twice */
1960 if (isect->next && isect->next->stroke == isect->stroke)
1962 float start_v[3], end_v[3];
1965 if (isect->gesture_index < isect->next->gesture_index)
1967 VecSubf(start_v, isect->p, gesture->points[0].p);
1968 VecSubf(end_v, sk_lastStrokePoint(gesture)->p, isect->next->p);
1972 VecSubf(start_v, isect->next->p, gesture->points[0].p);
1973 VecSubf(end_v, sk_lastStrokePoint(gesture)->p, isect->p);
1976 angle = VecAngle2(start_v, end_v);
1984 isect = isect->next;
1991 void sk_applyReverseGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
1993 SK_Intersection *isect;
1995 for (isect = list->first; isect; isect = isect->next)
1997 /* only reverse strokes that are crossed twice */
1998 if (isect->next && isect->next->stroke == isect->stroke)
2000 sk_reverseStroke(isect->stroke);
2003 isect = isect->next;
2008 void sk_applyGesture(SK_Sketch *sketch)
2010 ListBase intersections;
2011 ListBase self_intersections;
2012 SK_Stroke *segments = sk_createStroke();
2013 int nb_self_intersections, nb_intersections, nb_segments;
2015 intersections.first = intersections.last = NULL;
2016 self_intersections.first = self_intersections.last = NULL;
2018 nb_self_intersections = sk_getSelfIntersections(&self_intersections, sketch->gesture);
2019 nb_intersections = sk_getIntersections(&intersections, sketch, sketch->gesture);
2020 nb_segments = sk_getSegments(segments, sketch->gesture);
2022 /* detect and apply */
2023 if (nb_segments == 1 && nb_intersections == 1)
2025 sk_applyCutGesture(sketch, sketch->gesture, &intersections, segments);
2027 else if (nb_segments == 2 && nb_intersections == 1 && sk_detectTrimGesture(sketch, sketch->gesture, &intersections, segments))
2029 sk_applyTrimGesture(sketch, sketch->gesture, &intersections, segments);
2031 else if (nb_segments == 2 && nb_intersections == 2 && sk_detectDeleteGesture(sketch, sketch->gesture, &intersections, segments))
2033 sk_applyDeleteGesture(sketch, sketch->gesture, &intersections, segments);
2035 else if (nb_segments > 2 && nb_intersections == 2 && sk_detectMergeGesture(sketch, sketch->gesture, &intersections, segments))
2037 sk_applyMergeGesture(sketch, sketch->gesture, &intersections, segments);
2039 else if (nb_segments > 2 && nb_intersections == 2 && sk_detectReverseGesture(sketch, sketch->gesture, &intersections, segments))
2041 sk_applyReverseGesture(sketch, sketch->gesture, &intersections, segments);
2043 else if (nb_segments > 2 && nb_self_intersections == 1)
2046 BIF_undo_push("Convert Sketch");
2047 allqueue(REDRAWBUTSEDIT, 0);
2049 else if (nb_segments > 2 && nb_self_intersections == 2)
2051 sk_deleteSelectedStrokes(sketch);
2054 sk_freeStroke(segments);
2055 BLI_freelistN(&intersections);
2056 BLI_freelistN(&self_intersections);
2059 /********************************************/
2061 void sk_deleteSelectedStrokes(SK_Sketch *sketch)
2063 SK_Stroke *stk, *next;
2065 for (stk = sketch->strokes.first; stk; stk = next)
2069 if (stk->selected == 1)
2071 sk_removeStroke(sketch, stk);
2076 void sk_selectAllSketch(SK_Sketch *sketch, int mode)
2078 SK_Stroke *stk = NULL;
2082 for (stk = sketch->strokes.first; stk; stk = stk->next)
2089 for (stk = sketch->strokes.first; stk; stk = stk->next)
2098 for (stk = sketch->strokes.first; stk; stk = stk->next)
2100 selected &= stk->selected;
2105 for (stk = sketch->strokes.first; stk; stk = stk->next)
2107 stk->selected = selected;
2112 void sk_selectStroke(SK_Sketch *sketch)
2114 unsigned int buffer[MAXPICKBUF];
2115 short hits, mval[2];
2119 getmouseco_areawin(mval);
2120 hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-5, mval[1]-5, mval[0]+5, mval[1]+5);
2122 hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-12, mval[1]-12, mval[0]+12, mval[1]+12);
2126 int besthitresult = -1;
2129 besthitresult = buffer[3];
2132 besthitresult = buffer[3];
2133 /* loop and get best hit */
2136 if (besthitresult > 0)
2138 SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
2140 if ((G.qual & LR_SHIFTKEY) == 0)
2142 sk_selectAllSketch(sketch, -1);
2144 selected_stk->selected = 1;
2148 selected_stk->selected ^= 1;
2156 void sk_queueRedrawSketch(SK_Sketch *sketch)
2158 if (sketch->active_stroke != NULL)
2160 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2164 allqueue(REDRAWVIEW3D, 0);
2169 void sk_drawSketch(SK_Sketch *sketch, int with_names)
2173 glDisable(GL_DEPTH_TEST);
2175 glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE));
2176 glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
2181 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
2183 sk_drawStroke(stk, id, NULL);
2190 float selected_rgb[3] = {1, 0, 0};
2191 float unselected_rgb[3] = {1, 0.5, 0};
2193 for (stk = sketch->strokes.first; stk; stk = stk->next)
2195 sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb));
2197 if (stk->selected == 1)
2199 sk_drawStrokeSubdivision(stk);
2203 /* only draw gesture in active area */
2204 if (sketch->gesture != NULL && area_is_active_area(G.vd->area))
2206 float gesture_rgb[3] = {0, 0.5, 1};
2207 sk_drawStroke(sketch->gesture, -1, gesture_rgb);
2210 if (sketch->active_stroke != NULL)
2212 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2214 if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2216 sk_drawStrokeSubdivision(sketch->active_stroke);
2221 /* update point if in active area */
2222 if (area_is_active_area(G.vd->area))
2226 sk_initDrawData(&dd);
2227 sk_getStrokePoint(&sketch->next_point, sketch, sketch->active_stroke, &dd, G.qual);
2230 glEnable(GL_LINE_STIPPLE);
2231 glColor3f(1, 0.5, 0);
2232 glBegin(GL_LINE_STRIP);
2234 glVertex3fv(last->p);
2235 glVertex3fv(sketch->next_point.p);
2239 glDisable(GL_LINE_STIPPLE);
2241 switch (sketch->next_point.mode)
2244 glColor3f(0, 0.5, 1);
2256 glVertex3fv(sketch->next_point.p);
2266 glEnable(GL_DEPTH_TEST);
2269 int sk_paint(SK_Sketch *sketch, short mbut)
2273 if (mbut == LEFTMOUSE)
2276 if (sketch->active_stroke == NULL)
2278 sk_startStroke(sketch);
2281 sk_initDrawData(&dd);
2285 /* get current user input */
2286 getmouseco_areawin(dd.mval);
2288 /* only add current point to buffer if mouse moved (otherwise wait until it does) */
2289 if (sk_stroke_filtermval(&dd)) {
2291 sk_addStrokePoint(sketch, sketch->active_stroke, &dd, G.qual);
2292 sk_updateDrawData(&dd);
2297 BIF_wait_for_statechange();
2302 event = extern_qread(&val);
2305 /* do mouse checking at the end, so don't check twice, and potentially
2308 } while (get_mbut() & L_MOUSE);
2310 sk_endContinuousStroke(sketch->active_stroke);
2311 sk_filterLastContinuousStroke(sketch->active_stroke);
2312 sk_updateNextPoint(sketch);
2314 else if (mbut == RIGHTMOUSE)
2316 if (sketch->active_stroke != NULL)
2318 SK_Stroke *stk = sketch->active_stroke;
2320 sk_endStroke(sketch);
2322 if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2324 if (G.scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
2326 retargetStroke(stk);
2330 sk_convertStroke(stk);
2332 sk_removeStroke(sketch, stk);
2333 BIF_undo_push("Convert Sketch");
2334 allqueue(REDRAWBUTSEDIT, 0);
2337 allqueue(REDRAWVIEW3D, 0);
2339 /* no gestures in quick mode */
2340 else if (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2342 retval = 0; /* return zero for default click behavior */
2347 sketch->gesture = sk_createStroke();
2349 sk_initDrawData(&dd);
2353 /* get current user input */
2354 getmouseco_areawin(dd.mval);
2356 /* only add current point to buffer if mouse moved (otherwise wait until it does) */
2357 if (sk_stroke_filtermval(&dd)) {
2359 sk_addStrokeDrawPoint(sketch, sketch->gesture, &dd);
2360 sk_updateDrawData(&dd);
2362 /* draw only if mouse has moved */
2363 if (sketch->gesture->nb_points > 1)
2370 BIF_wait_for_statechange();
2375 event = extern_qread(&val);
2378 /* do mouse checking at the end, so don't check twice, and potentially
2381 } while (get_mbut() & R_MOUSE);
2383 sk_endContinuousStroke(sketch->gesture);
2384 sk_filterLastContinuousStroke(sketch->gesture);
2385 sk_filterLastContinuousStroke(sketch->gesture);
2386 sk_filterLastContinuousStroke(sketch->gesture);
2388 if (sketch->gesture->nb_points == 1)
2390 sk_selectStroke(sketch);
2394 /* apply gesture here */
2395 sk_applyGesture(sketch);
2398 sk_freeStroke(sketch->gesture);
2399 sketch->gesture = NULL;
2401 allqueue(REDRAWVIEW3D, 0);
2408 void BDR_drawSketchNames()
2410 if (BIF_validSketchMode())
2412 if (GLOBAL_sketch != NULL)
2414 sk_drawSketch(GLOBAL_sketch, 1);
2419 void BDR_drawSketch()
2421 if (BIF_validSketchMode())
2423 if (GLOBAL_sketch != NULL)
2425 sk_drawSketch(GLOBAL_sketch, 0);
2430 void BIF_endStrokeSketch()
2432 if (BIF_validSketchMode())
2434 if (GLOBAL_sketch != NULL)
2436 sk_endStroke(GLOBAL_sketch);
2437 allqueue(REDRAWVIEW3D, 0);
2442 void BIF_cancelStrokeSketch()
2444 if (BIF_validSketchMode())
2446 if (GLOBAL_sketch != NULL)
2448 sk_cancelStroke(GLOBAL_sketch);
2449 allqueue(REDRAWVIEW3D, 0);
2454 void BIF_deleteSketch()
2456 if (BIF_validSketchMode())
2458 if (GLOBAL_sketch != NULL)
2460 sk_deleteSelectedStrokes(GLOBAL_sketch);
2461 allqueue(REDRAWVIEW3D, 0);
2466 void BIF_convertSketch()
2468 if (BIF_validSketchMode())
2470 if (GLOBAL_sketch != NULL)
2472 sk_convert(GLOBAL_sketch);
2473 BIF_undo_push("Convert Sketch");
2474 allqueue(REDRAWVIEW3D, 0);
2475 allqueue(REDRAWBUTSEDIT, 0);
2480 int BIF_paintSketch(short mbut)
2482 if (BIF_validSketchMode())
2484 if (GLOBAL_sketch == NULL)
2486 GLOBAL_sketch = sk_createSketch();
2489 return sk_paint(GLOBAL_sketch, mbut);
2498 void BDR_queueDrawSketch()
2500 if (BIF_validSketchMode())
2502 if (GLOBAL_sketch != NULL)
2504 sk_queueRedrawSketch(GLOBAL_sketch);
2509 void BIF_selectAllSketch(int mode)
2511 if (BIF_validSketchMode())
2513 if (GLOBAL_sketch != NULL)
2515 sk_selectAllSketch(GLOBAL_sketch, mode);
2516 allqueue(REDRAWVIEW3D, 0);
2521 int BIF_validSketchMode()
2524 G.obedit->type == OB_ARMATURE &&
2525 G.scene->toolsettings->bone_sketching & BONE_SKETCHING)
2535 int BIF_fullSketchMode()
2538 G.obedit->type == OB_ARMATURE &&
2539 G.scene->toolsettings->bone_sketching & BONE_SKETCHING &&
2540 (G.scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK) == 0)