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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * ***** END GPL LICENSE BLOCK *****
27 #include "MEM_guardedalloc.h"
29 #include "DNA_object_types.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_armature_types.h"
33 #include "RNA_define.h"
34 #include "RNA_access.h"
36 #include "BLI_blenlib.h"
38 #include "BLI_utildefines.h"
39 #include "BLI_graph.h"
40 #include "BLI_ghash.h"
42 #include "BKE_context.h"
43 #include "BKE_sketch.h"
45 #include "ED_view3d.h"
46 #include "ED_screen.h"
49 //#include "BIF_screen.h"
50 //#include "BIF_space.h"
51 //#include "BIF_mywindow.h"
52 #include "ED_armature.h"
53 #include "armature_intern.h"
54 //#include "BIF_sketch.h"
55 #include "BIF_retarget.h"
56 #include "BIF_generate.h"
57 //#include "BIF_interface.h"
59 #include "ED_transform.h"
64 //#include "blendef.h"
65 //#include "mydevice.h"
70 typedef int (*GestureDetectFct)(bContext*, SK_Gesture*, SK_Sketch *);
71 typedef void (*GestureApplyFct)(bContext*, SK_Gesture*, SK_Sketch *);
73 typedef struct SK_GestureAction {
75 GestureDetectFct detect;
76 GestureApplyFct apply;
79 static SK_Point boneSnap;
80 static int LAST_SNAP_POINT_VALID = 0;
81 static float LAST_SNAP_POINT[3];
84 typedef struct SK_StrokeIterator {
98 /*********************************/
105 /******************** PROTOTYPES ******************************/
107 void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
109 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
110 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
111 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
112 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
113 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
114 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
115 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
116 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
117 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
118 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
119 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
120 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
121 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
122 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
124 SK_Sketch* contextSketch(const bContext *c, int create);
125 SK_Sketch* viewcontextSketch(ViewContext *vc, int create);
127 void sk_resetOverdraw(SK_Sketch *sketch);
128 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
130 /******************** GESTURE ACTIONS ******************************/
132 static SK_GestureAction GESTURE_ACTIONS[] =
134 {"Cut", sk_detectCutGesture, sk_applyCutGesture},
135 {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
136 {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
137 {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
138 {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
139 {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
140 {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
144 /******************** TEMPLATES UTILS *************************/
146 static char *TEMPLATES_MENU = NULL;
147 static int TEMPLATES_CURRENT = 0;
148 static GHash *TEMPLATES_HASH = NULL;
149 static RigGraph *TEMPLATE_RIGG = NULL;
151 void BIF_makeListTemplates(const bContext *C)
153 Object *obedit = CTX_data_edit_object(C);
154 Scene *scene = CTX_data_scene(C);
155 ToolSettings *ts = CTX_data_tool_settings(C);
159 if (TEMPLATES_HASH != NULL)
161 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
164 TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "makeListTemplates gh");
165 TEMPLATES_CURRENT = 0;
167 for ( base = FIRSTBASE; base; base = base->next )
169 Object *ob = base->object;
171 if (ob != obedit && ob->type == OB_ARMATURE)
174 BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
176 if (ob == ts->skgen_template)
178 TEMPLATES_CURRENT = index;
184 char *BIF_listTemplates(const bContext *UNUSED(C))
187 char menu_header[] = "Template%t|None%x0|";
190 if (TEMPLATES_MENU != NULL)
192 MEM_freeN(TEMPLATES_MENU);
195 TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
199 p += sprintf(TEMPLATES_MENU, "%s", menu_header);
201 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
203 while (!BLI_ghashIterator_isDone(&ghi))
205 Object *ob = BLI_ghashIterator_getValue(&ghi);
206 int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
208 p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
210 BLI_ghashIterator_step(&ghi);
213 return TEMPLATES_MENU;
216 int BIF_currentTemplate(const bContext *C)
218 ToolSettings *ts = CTX_data_tool_settings(C);
220 if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL)
223 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
225 while (!BLI_ghashIterator_isDone(&ghi))
227 Object *ob = BLI_ghashIterator_getValue(&ghi);
228 int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
230 if (ob == ts->skgen_template)
232 TEMPLATES_CURRENT = key;
236 BLI_ghashIterator_step(&ghi);
240 return TEMPLATES_CURRENT;
243 static RigGraph* sk_makeTemplateGraph(const bContext *C, Object *ob)
245 Object *obedit = CTX_data_edit_object(C);
253 if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
255 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
256 TEMPLATE_RIGG = NULL;
259 if (TEMPLATE_RIGG == NULL)
265 TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm);
269 return TEMPLATE_RIGG;
272 int BIF_nbJointsTemplate(const bContext *C)
274 ToolSettings *ts = CTX_data_tool_settings(C);
275 RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template);
279 return RIG_nbJoints(rg);
287 const char * BIF_nameBoneTemplate(const bContext *C)
289 ToolSettings *ts = CTX_data_tool_settings(C);
290 SK_Sketch *stk = contextSketch(C, 1);
294 if (stk && stk->active_stroke != NULL)
296 index = stk->active_stroke->nb_points;
299 rg = sk_makeTemplateGraph(C, ts->skgen_template);
306 return RIG_nameBone(rg, 0, index);
309 void BIF_freeTemplates(bContext *UNUSED(C))
311 if (TEMPLATES_MENU != NULL)
313 MEM_freeN(TEMPLATES_MENU);
314 TEMPLATES_MENU = NULL;
317 if (TEMPLATES_HASH != NULL)
319 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
320 TEMPLATES_HASH = NULL;
323 if (TEMPLATE_RIGG != NULL)
325 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
326 TEMPLATE_RIGG = NULL;
330 void BIF_setTemplate(bContext *C, int index)
332 ToolSettings *ts = CTX_data_tool_settings(C);
335 ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
339 ts->skgen_template = NULL;
341 if (TEMPLATE_RIGG != NULL)
343 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
345 TEMPLATE_RIGG = NULL;
349 /*********************** CONVERSION ***************************/
351 static void sk_autoname(bContext *C, ReebArc *arc)
353 ToolSettings *ts = CTX_data_tool_settings(C);
354 if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME)
358 char *num = ts->skgen_num_string;
361 BLI_snprintf(num, 8, "%i", i);
365 char *side = ts->skgen_side_string;
369 if (BLI_streq(side, ""))
373 else if (BLI_streq(side, "R") || BLI_streq(side, "L"))
378 else if (BLI_streq(side, "r") || BLI_streq(side, "l"))
386 if (arc->head->p[0] < 0)
388 BLI_snprintf(side, 8, caps?"R":"r");
392 BLI_snprintf(side, 8, caps?"L":"l");
399 static ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
403 node = MEM_callocN(sizeof(ReebNode), "reeb node");
404 VECCOPY(node->p, pt->p);
405 mul_m4_v3(imat, node->p);
407 VECCOPY(node->no, pt->no);
408 mul_m3_v3(tmat, node->no);
413 static ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
418 arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
419 arc->head = sk_pointToNode(stk->points, imat, tmat);
420 arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
422 arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
423 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
425 for (i = 0; i < arc->bcount; i++)
427 VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
428 mul_m4_v3(imat, arc->buckets[i].p);
430 VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
431 mul_m3_v3(tmat, arc->buckets[i].no);
437 static void sk_retargetStroke(bContext *C, SK_Stroke *stk)
439 ToolSettings *ts = CTX_data_tool_settings(C);
440 Object *obedit = CTX_data_edit_object(C);
446 invert_m4_m4(imat, obedit->obmat);
448 copy_m3_m4(tmat, obedit->obmat);
451 arc = sk_strokeToArc(stk, imat, tmat);
455 rg = sk_makeTemplateGraph(C, ts->skgen_template);
457 BIF_retargetArc(C, arc, rg);
459 sk_autoname(C, NULL);
461 MEM_freeN(arc->head);
462 MEM_freeN(arc->tail);
463 REEB_freeArc((BArc*)arc);
466 /**************************************************************/
468 static void sk_cancelStroke(SK_Sketch *sketch)
470 if (sketch->active_stroke != NULL)
472 sk_resetOverdraw(sketch);
473 sk_removeStroke(sketch, sketch->active_stroke);
478 static float sk_clampPointSize(SK_Point *pt, float size)
480 return MAX2(size * pt->size, size / 2);
483 static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
485 glTranslatef(pt->p[0], pt->p[1], pt->p[2]);
486 gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
489 static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float size)
491 float vec1[3], vec2[3] = {0, 0, 1}, axis[3];
494 sub_v3_v3v3(vec1, pt1->p, pt0->p);
495 length = normalize_v3(vec1);
496 cross_v3_v3v3(axis, vec2, vec1);
498 if (is_zero_v3(axis))
503 angle = angle_normalized_v3v3(vec2, vec1);
505 glRotatef(angle * 180 / M_PI + 180, axis[0], axis[1], axis[2]);
507 gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
510 static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float height)
512 float vec2[3] = {0, 0, 1}, axis[3];
517 cross_v3_v3v3(axis, vec2, pt->no);
519 if (is_zero_v3(axis))
524 angle = angle_normalized_v3v3(vec2, pt->no);
526 glRotatef(angle * 180 / M_PI, axis[0], axis[1], axis[2]);
529 gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
534 static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
538 GLUquadric *quad = gluNewQuadric();
539 gluQuadricNormals(quad, GLU_SMOOTH);
545 for (i = 0; i < stk->nb_points; i++)
549 sk_drawPoint(quad, stk->points + i, 0.1);
553 sk_drawEdge(quad, stk->points + i - 1, stk->points + i, 0.1);
562 float d_rgb[3] = {1, 1, 1};
564 copy_v3_v3(rgb, color);
565 sub_v3_v3(d_rgb, rgb);
566 mul_v3_fl(d_rgb, 1.0f / (float)stk->nb_points);
568 for (i = 0; i < stk->nb_points; i++)
570 SK_Point *pt = stk->points + i;
574 if (pt->type == PT_EXACT)
577 sk_drawPoint(quad, pt, 0.15);
578 sk_drawNormal(quad, pt, 0.05, 0.9);
581 if (i >= start && i <= end)
583 glColor3f(0.3, 0.3, 0.3);
590 if (pt->type != PT_EXACT)
593 sk_drawPoint(quad, pt, 0.1);
598 sk_drawEdge(quad, pt - 1, pt, 0.1);
603 add_v3_v3(rgb, d_rgb);
607 gluDeleteQuadric(quad);
610 static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
612 SK_Stroke *stk = ((SK_StrokeIterator*)iter)->stroke;
613 float head[3], tail[3];
615 int end = iter->length;
617 GLUquadric *quad = gluNewQuadric();
618 gluQuadricNormals(quad, GLU_SMOOTH);
621 VECCOPY(head, iter->p);
623 index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
626 SK_Point *pt = stk->points + index;
631 sk_drawPoint(quad, pt, 0.15);
633 sk_drawNormal(quad, pt, 0.05, 0.9);
638 bone_start = index; // start next bone from current index
640 index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
643 gluDeleteQuadric(quad);
646 static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
651 if (toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
657 for (i = 0; i < stk->nb_points; i++)
659 SK_Point *pt = stk->points + i;
661 if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
663 if (head_index == -1)
669 if (i - head_index > 1)
671 SK_StrokeIterator sk_iter;
672 BArcIterator *iter = (BArcIterator*)&sk_iter;
674 initStrokeIterator(iter, stk, head_index, i);
676 if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
678 drawSubdividedStrokeBy(toolsettings, iter, nextAdaptativeSubdivision);
680 else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
682 drawSubdividedStrokeBy(toolsettings, iter, nextLengthSubdivision);
684 else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
686 drawSubdividedStrokeBy(toolsettings, iter, nextFixedSubdivision);
697 static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts)
699 ARegion *ar = CTX_wm_region(C);
703 for (i = 0; i < stk->nb_points; i++)
705 if (all_pts || stk->points[i].type == PT_EXACT)
710 project_short_noclip(ar, stk->points[i].p, pval);
712 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
717 pt = stk->points + i;
730 static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, short mval[2], int *dist)
732 ARegion *ar = CTX_wm_region(C);
736 for (bone = ebones->first; bone; bone = bone->next)
742 if ((bone->flag & BONE_CONNECTED) == 0)
744 VECCOPY(vec, bone->head);
745 mul_m4_v3(ob->obmat, vec);
746 project_short_noclip(ar, vec, pval);
748 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
760 VECCOPY(vec, bone->tail);
761 mul_m4_v3(ob->obmat, vec);
762 project_short_noclip(ar, vec, pval);
764 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
778 void sk_resetOverdraw(SK_Sketch *sketch)
780 sketch->over.target = NULL;
781 sketch->over.start = -1;
782 sketch->over.end = -1;
783 sketch->over.count = 0;
786 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
788 return sketch->over.target &&
789 sketch->over.count >= SK_OVERDRAW_LIMIT &&
790 (sketch->over.target == stk || stk == NULL) &&
791 (sketch->over.start != -1 || sketch->over.end != -1);
794 static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
796 if (sketch->over.target == NULL)
799 int closest_index = -1;
800 int dist = SNAP_MIN_DISTANCE * 2;
802 for (target = sketch->strokes.first; target; target = target->next)
808 SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
812 sketch->over.target = target;
813 closest_index = index;
818 if (sketch->over.target != NULL)
820 if (closest_index > -1)
822 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
824 sketch->over.count = SK_OVERDRAW_LIMIT;
828 sketch->over.count++;
832 if (stk->nb_points == 1)
834 sketch->over.start = closest_index;
838 sketch->over.end = closest_index;
842 else if (sketch->over.target != NULL)
844 SK_Point *closest_pt = NULL;
845 int dist = SNAP_MIN_DISTANCE * 2;
848 closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
850 if (closest_pt != NULL)
852 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
854 sketch->over.count = SK_OVERDRAW_LIMIT;
858 sketch->over.count++;
861 sketch->over.end = index;
865 sketch->over.end = -1;
870 /* return 1 on reverse needed */
871 static int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
875 *start = sketch->over.start;
876 *end = sketch->over.end;
885 *end = sketch->over.target->nb_points - 1;
899 static void sk_endOverdraw(SK_Sketch *sketch)
901 SK_Stroke *stk = sketch->active_stroke;
903 if (sk_hasOverdraw(sketch, NULL))
908 if (sk_adjustIndexes(sketch, &start, &end))
910 sk_reverseStroke(stk);
913 if (stk->nb_points > 1)
915 stk->points->type = sketch->over.target->points[start].type;
916 sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
919 sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
921 sk_removeStroke(sketch, stk);
923 sk_resetOverdraw(sketch);
928 static void sk_startStroke(SK_Sketch *sketch)
930 SK_Stroke *stk = sk_createStroke();
932 BLI_addtail(&sketch->strokes, stk);
933 sketch->active_stroke = stk;
935 sk_resetOverdraw(sketch);
938 static void sk_endStroke(bContext *C, SK_Sketch *sketch)
940 ToolSettings *ts = CTX_data_tool_settings(C);
941 sk_shrinkStrokeBuffer(sketch->active_stroke);
943 if (ts->bone_sketching & BONE_SKETCHING_ADJUST)
945 sk_endOverdraw(sketch);
948 sketch->active_stroke = NULL;
951 static void sk_updateDrawData(SK_DrawData *dd)
953 dd->type = PT_CONTINUOUS;
955 dd->previous_mval[0] = dd->mval[0];
956 dd->previous_mval[1] = dd->mval[1];
959 static float sk_distanceDepth(bContext *C, float p1[3], float p2[3])
961 ARegion *ar = CTX_wm_region(C);
962 RegionView3D *rv3d = ar->regiondata;
966 sub_v3_v3v3(vec, p1, p2);
968 project_v3_v3v3(vec, vec, rv3d->viewinv[2]);
970 distance = len_v3(vec);
972 if (dot_v3v3(rv3d->viewinv[2], vec) > 0)
980 static void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance)
982 ARegion *ar = CTX_wm_region(C);
983 ScrArea *sa = CTX_wm_area(C);
984 View3D *v3d = sa->spacedata.first;
989 progress = len_v3v3(stk->points[start].p, stk->points[start - 1].p);
991 for (i = start; i <= end; i++)
993 float ray_start[3], ray_normal[3];
994 float delta = len_v3v3(stk->points[i].p, stk->points[i + 1].p);
997 project_float(ar, stk->points[i].p, pval);
998 viewray(ar, v3d, pval, ray_start, ray_normal);
1000 mul_v3_fl(ray_normal, distance * progress / length);
1001 add_v3_v3(stk->points[i].p, ray_normal);
1007 static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd)
1009 ARegion *ar = CTX_wm_region(C);
1010 /* copied from grease pencil, need fixing */
1011 SK_Point *last = sk_lastStrokePoint(stk);
1013 float fp[3] = {0, 0, 0};
1018 VECCOPY(fp, last->p);
1021 initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
1023 /* method taken from editview.c - mouse_cursor() */
1024 project_short_noclip(ar, fp, cval);
1025 window_to_3d_delta(ar, dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
1026 sub_v3_v3v3(vec, fp, dvec);
1029 static int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *UNUSED(sketch), SK_Stroke *stk, SK_DrawData *dd)
1031 pt->type = dd->type;
1032 pt->mode = PT_PROJECT;
1033 sk_projectDrawPoint(C, pt->p, stk, dd);
1038 static int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1040 ARegion *ar = CTX_wm_region(C);
1041 RegionView3D *rv3d = ar->regiondata;
1044 sk_initPoint(&pt, dd, rv3d->viewinv[2]);
1046 sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd);
1048 sk_appendStrokePoint(stk, &pt);
1053 static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1055 ToolSettings *ts = CTX_data_tool_settings(C);
1056 int point_added = 0;
1058 if (ts->snap_mode == SCE_SNAP_MODE_VOLUME)
1061 float *last_p = NULL;
1062 float dist = FLT_MAX;
1067 BLI_freelistN(&sketch->depth_peels);
1068 sketch->depth_peels.first = sketch->depth_peels.last = NULL;
1070 mvalf[0]= dd->mval[0];
1071 mvalf[1]= dd->mval[1];
1072 peelObjectsContext(C, &sketch->depth_peels, mvalf);
1074 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
1076 last_p = stk->points[stk->nb_points - 1].p;
1078 else if (LAST_SNAP_POINT_VALID)
1080 last_p = LAST_SNAP_POINT;
1084 for (p1 = sketch->depth_peels.first; p1; p1 = p1->next)
1095 /* if peeling objects, take the first and last from each object */
1096 if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT)
1099 for (peel = p1->next; peel; peel = peel->next)
1101 if (peel->ob == p1->ob)
1108 /* otherwise, pair first with second and so on */
1111 for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
1113 /* nothing to do here */
1121 add_v3_v3v3(vec, p1->p, p2->p);
1122 mul_v3_fl(vec, 0.5f);
1123 new_size = len_v3v3(p1->p, p2->p);
1127 VECCOPY(vec, p1->p);
1138 new_dist = len_v3v3(last_p, vec);
1140 if (new_dist < dist)
1149 if (dist != FLT_MAX)
1151 pt->type = dd->type;
1153 pt->size = size / 2;
1159 //BLI_freelistN(&depth_peels);
1163 SK_Stroke *snap_stk;
1168 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
1170 /* snap to strokes */
1171 // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
1172 for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
1174 SK_Point *spt = NULL;
1175 if (snap_stk == stk)
1177 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
1181 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
1186 VECCOPY(pt->p, spt->p);
1191 mval[0] = dd->mval[0];
1192 mval[1] = dd->mval[1];
1194 /* try to snap to closer object */
1195 found = snapObjectsContext(C, mval, &dist, vec, no, SNAP_NOT_SELECTED);
1198 pt->type = dd->type;
1200 VECCOPY(pt->p, vec);
1209 static int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1212 ARegion *ar = CTX_wm_region(C);
1213 RegionView3D *rv3d = ar->regiondata;
1216 sk_initPoint(&pt, dd, rv3d->viewinv[2]);
1218 point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
1223 float length, distance;
1227 VECCOPY(final_p, pt.p);
1229 sk_projectDrawPoint(C, pt.p, stk, dd);
1230 sk_appendStrokePoint(stk, &pt);
1232 /* update all previous point to give smooth Z progresion */
1235 for (i = stk->nb_points - 2; i > 0; i--)
1237 length += len_v3v3(stk->points[i].p, stk->points[i + 1].p);
1239 if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
1247 distance = sk_distanceDepth(C, final_p, stk->points[i].p);
1249 sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
1252 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1260 static void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
1262 ToolSettings *ts = CTX_data_tool_settings(C);
1263 int point_added = 0;
1267 point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
1270 if (point_added == 0)
1272 point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
1275 if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST)
1277 sk_updateOverdraw(C, sketch, stk, dd);
1281 static void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
1283 int point_added = 0;
1287 point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
1288 LAST_SNAP_POINT_VALID = 1;
1289 VECCOPY(LAST_SNAP_POINT, pt->p);
1293 LAST_SNAP_POINT_VALID = 0;
1296 if (point_added == 0)
1298 point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
1302 /********************************************/
1304 static void* headPoint(void *arg);
1305 static void* tailPoint(void *arg);
1306 static void* nextPoint(void *arg);
1307 static void* nextNPoint(void *arg, int n);
1308 static void* peekPoint(void *arg, int n);
1309 static void* previousPoint(void *arg);
1310 static int iteratorStopped(void *arg);
1312 static void initIteratorFct(SK_StrokeIterator *iter)
1314 iter->head = headPoint;
1315 iter->tail = tailPoint;
1316 iter->peek = peekPoint;
1317 iter->next = nextPoint;
1318 iter->nextN = nextNPoint;
1319 iter->previous = previousPoint;
1320 iter->stopped = iteratorStopped;
1323 static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
1325 SK_Point *pt = NULL;
1327 if (index >= 0 && index < iter->length)
1329 pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
1332 iter->size = pt->size;
1344 void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
1346 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1348 initIteratorFct(iter);
1353 iter->start = start + 1;
1354 iter->end = end - 1;
1359 iter->start = start - 1;
1360 iter->end = end + 1;
1364 iter->length = iter->stride * (iter->end - iter->start + 1);
1370 static void* headPoint(void *arg)
1372 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1373 SK_Point *result = NULL;
1375 result = &(iter->stroke->points[iter->start - iter->stride]);
1376 iter->p = result->p;
1377 iter->no = result->no;
1378 iter->size = result->size;
1383 static void* tailPoint(void *arg)
1385 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1386 SK_Point *result = NULL;
1388 result = &(iter->stroke->points[iter->end + iter->stride]);
1389 iter->p = result->p;
1390 iter->no = result->no;
1391 iter->size = result->size;
1396 static void* nextPoint(void *arg)
1398 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1399 SK_Point *result = NULL;
1402 if (iter->index < iter->length)
1404 result = setIteratorValues(iter, iter->index);
1410 static void* nextNPoint(void *arg, int n)
1412 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1413 SK_Point *result = NULL;
1417 /* check if passed end */
1418 if (iter->index < iter->length)
1420 result = setIteratorValues(iter, iter->index);
1426 static void* peekPoint(void *arg, int n)
1428 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1429 SK_Point *result = NULL;
1430 int index = iter->index + n;
1432 /* check if passed end */
1433 if (index < iter->length)
1435 result = setIteratorValues(iter, index);
1441 static void* previousPoint(void *arg)
1443 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1444 SK_Point *result = NULL;
1446 if (iter->index > 0)
1449 result = setIteratorValues(iter, iter->index);
1455 static int iteratorStopped(void *arg)
1457 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1459 if (iter->index >= iter->length)
1469 static void sk_convertStroke(bContext *C, SK_Stroke *stk)
1471 Object *obedit = CTX_data_edit_object(C);
1472 ToolSettings *ts = CTX_data_tool_settings(C);
1473 bArmature *arm = obedit->data;
1475 EditBone *parent = NULL;
1476 float invmat[4][4]; /* move in caller function */
1483 invert_m4_m4(invmat, obedit->obmat);
1485 copy_m3_m4(tmat, obedit->obmat);
1488 for (i = 0; i < stk->nb_points; i++)
1490 SK_Point *pt = stk->points + i;
1492 if (pt->type == PT_EXACT)
1501 EditBone *bone = NULL;
1502 EditBone *new_parent;
1504 if (i - head_index > 1)
1506 SK_StrokeIterator sk_iter;
1507 BArcIterator *iter = (BArcIterator*)&sk_iter;
1509 initStrokeIterator(iter, stk, head_index, i);
1511 if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1513 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
1515 else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1517 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
1519 else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1521 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
1527 bone = ED_armature_edit_bone_add(arm, "Bone");
1529 VECCOPY(bone->head, head->p);
1530 VECCOPY(bone->tail, pt->p);
1532 mul_m4_v3(invmat, bone->head);
1533 mul_m4_v3(invmat, bone->tail);
1534 setBoneRollFromNormal(bone, head->no, invmat, tmat);
1538 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
1540 /* move to end of chain */
1541 while (bone->parent != NULL)
1543 bone = bone->parent;
1544 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
1549 bone->parent = parent;
1550 bone->flag |= BONE_CONNECTED;
1553 parent = new_parent;
1561 static void sk_convert(bContext *C, SK_Sketch *sketch)
1563 ToolSettings *ts = CTX_data_tool_settings(C);
1566 for (stk = sketch->strokes.first; stk; stk = stk->next)
1568 if (stk->selected == 1)
1570 if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
1572 sk_retargetStroke(C, stk);
1576 sk_convertStroke(C, stk);
1579 // allqueue(REDRAWBUTSEDIT, 0);
1583 /******************* GESTURE *************************/
1586 /* returns the number of self intersections */
1587 static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
1589 ARegion *ar = CTX_wm_region(C);
1593 for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
1595 float s_p1[3] = {0, 0, 0};
1596 float s_p2[3] = {0, 0, 0};
1599 project_float(ar, gesture->points[s_i].p, s_p1);
1600 project_float(ar, gesture->points[s_i + 1].p, s_p2);
1602 /* start checking from second next, because two consecutive cannot intersect */
1603 for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
1605 float g_p1[3] = {0, 0, 0};
1606 float g_p2[3] = {0, 0, 0};
1610 project_float(ar, gesture->points[g_i].p, g_p1);
1611 project_float(ar, gesture->points[g_i + 1].p, g_p2);
1613 if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
1615 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
1617 isect->gesture_index = g_i;
1618 isect->before = s_i;
1619 isect->after = s_i + 1;
1620 isect->stroke = gesture;
1622 sub_v3_v3v3(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
1623 mul_v3_fl(isect->p, lambda);
1624 add_v3_v3(isect->p, gesture->points[s_i].p);
1626 BLI_addtail(list, isect);
1636 static int cmpIntersections(void *i1, void *i2)
1638 SK_Intersection *isect1 = i1, *isect2 = i2;
1640 if (isect1->stroke == isect2->stroke)
1642 if (isect1->before < isect2->before)
1646 else if (isect1->before > isect2->before)
1652 if (isect1->lambda < isect2->lambda)
1656 else if (isect1->lambda > isect2->lambda)
1667 /* returns the maximum number of intersections per stroke */
1668 static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
1670 ARegion *ar = CTX_wm_region(C);
1671 ScrArea *sa = CTX_wm_area(C);
1672 View3D *v3d = sa->spacedata.first;
1676 for (stk = sketch->strokes.first; stk; stk = stk->next)
1681 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
1683 float s_p1[3] = {0, 0, 0};
1684 float s_p2[3] = {0, 0, 0};
1687 project_float(ar, stk->points[s_i].p, s_p1);
1688 project_float(ar, stk->points[s_i + 1].p, s_p2);
1690 for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
1692 float g_p1[3] = {0, 0, 0};
1693 float g_p2[3] = {0, 0, 0};
1697 project_float(ar, gesture->points[g_i].p, g_p1);
1698 project_float(ar, gesture->points[g_i + 1].p, g_p2);
1700 if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
1702 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
1703 float ray_start[3], ray_end[3];
1706 isect->gesture_index = g_i;
1707 isect->before = s_i;
1708 isect->after = s_i + 1;
1709 isect->stroke = stk;
1710 isect->lambda = lambda;
1714 viewline(ar, v3d, mval, ray_start, ray_end);
1716 isect_line_line_v3( stk->points[s_i].p,
1717 stk->points[s_i + 1].p,
1723 BLI_addtail(list, isect);
1730 added = MAX2(s_added, added);
1733 BLI_sortlist(list, cmpIntersections);
1738 static int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
1740 SK_StrokeIterator sk_iter;
1741 BArcIterator *iter = (BArcIterator*)&sk_iter;
1743 float CORRELATION_THRESHOLD = 0.99f;
1747 sk_appendStrokePoint(segments, &gesture->points[0]);
1748 vec = segments->points[segments->nb_points - 1].p;
1750 initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
1752 for (i = 1, j = 0; i < gesture->nb_points; i++)
1756 /* Calculate normal */
1757 sub_v3_v3v3(n, gesture->points[i].p, vec);
1759 if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
1762 sk_appendStrokePoint(segments, &gesture->points[j]);
1763 vec = segments->points[segments->nb_points - 1].p;
1764 segments->points[segments->nb_points - 1].type = PT_EXACT;
1768 sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
1770 return segments->nb_points - 1;
1773 int sk_detectCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1775 if (gest->nb_segments == 1 && gest->nb_intersections == 1)
1783 void sk_applyCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1785 SK_Intersection *isect;
1787 for (isect = gest->intersections.first; isect; isect = isect->next)
1792 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
1793 VECCOPY(pt.p, isect->p);
1794 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
1796 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
1800 int sk_detectTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1802 if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
1807 sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p);
1808 sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p);
1810 angle = RAD2DEG(angle_v2v2(s1, s2));
1812 if (angle > 60 && angle < 120)
1821 void sk_applyTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1823 SK_Intersection *isect;
1826 sub_v3_v3v3(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
1828 for (isect = gest->intersections.first; isect; isect = isect->next)
1831 float stroke_dir[3];
1834 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
1835 VECCOPY(pt.p, isect->p);
1836 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
1838 sub_v3_v3v3(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
1840 /* same direction, trim end */
1841 if (dot_v3v3(stroke_dir, trim_dir) > 0)
1843 sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
1844 sk_trimStroke(isect->stroke, 0, isect->after);
1846 /* else, trim start */
1849 sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
1850 sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
1856 int sk_detectCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1858 if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
1860 SK_Intersection *isect, *self_isect;
1862 /* get the the last intersection of the first pair */
1863 for( isect = gest->intersections.first; isect; isect = isect->next )
1865 if (isect->stroke == isect->next->stroke)
1867 isect = isect->next;
1872 self_isect = gest->self_intersections.first;
1874 if (isect && isect->gesture_index < self_isect->gesture_index)
1883 void sk_applyCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1885 SK_Intersection *isect;
1889 // command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
1890 if(command < 1) return;
1892 for (isect = gest->intersections.first; isect; isect = isect->next)
1894 SK_Intersection *i2;
1898 if (i2 && i2->stroke == isect->stroke)
1903 sk_flattenStroke(isect->stroke, isect->before, i2->after);
1906 sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
1909 sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
1918 int sk_detectDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1920 if (gest->nb_segments == 2 && gest->nb_intersections == 2)
1925 sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p);
1926 sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p);
1928 angle = RAD2DEG(angle_v2v2(s1, s2));
1939 void sk_applyDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *sketch)
1941 SK_Intersection *isect;
1943 for (isect = gest->intersections.first; isect; isect = isect->next)
1945 /* only delete strokes that are crossed twice */
1946 if (isect->next && isect->next->stroke == isect->stroke)
1948 isect = isect->next;
1950 sk_removeStroke(sketch, isect->stroke);
1955 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
1957 ARegion *ar = CTX_wm_region(C);
1958 if (gest->nb_segments > 2 && gest->nb_intersections == 2)
1960 short start_val[2], end_val[2];
1963 project_short_noclip(ar, gest->stk->points[0].p, start_val);
1964 project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
1966 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
1968 /* if gesture is a circle */
1971 SK_Intersection *isect;
1973 /* check if it circled around an exact point */
1974 for (isect = gest->intersections.first; isect; isect = isect->next)
1976 /* only delete strokes that are crossed twice */
1977 if (isect->next && isect->next->stroke == isect->stroke)
1979 int start_index, end_index;
1982 start_index = MIN2(isect->after, isect->next->after);
1983 end_index = MAX2(isect->before, isect->next->before);
1985 for (i = start_index; i <= end_index; i++)
1987 if (isect->stroke->points[i].type == PT_EXACT)
1989 return 1; /* at least one exact point found, stop detect here */
1994 isect = isect->next;
2003 void sk_applyMergeGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
2005 SK_Intersection *isect;
2007 /* check if it circled around an exact point */
2008 for (isect = gest->intersections.first; isect; isect = isect->next)
2010 /* only merge strokes that are crossed twice */
2011 if (isect->next && isect->next->stroke == isect->stroke)
2013 int start_index, end_index;
2016 start_index = MIN2(isect->after, isect->next->after);
2017 end_index = MAX2(isect->before, isect->next->before);
2019 for (i = start_index; i <= end_index; i++)
2021 /* if exact, switch to continuous */
2022 if (isect->stroke->points[i].type == PT_EXACT)
2024 isect->stroke->points[i].type = PT_CONTINUOUS;
2029 isect = isect->next;
2034 int sk_detectReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
2036 if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
2038 SK_Intersection *isect;
2040 /* check if it circled around an exact point */
2041 for (isect = gest->intersections.first; isect; isect = isect->next)
2043 /* only delete strokes that are crossed twice */
2044 if (isect->next && isect->next->stroke == isect->stroke)
2046 float start_v[3], end_v[3];
2049 if (isect->gesture_index < isect->next->gesture_index)
2051 sub_v3_v3v3(start_v, isect->p, gest->stk->points[0].p);
2052 sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
2056 sub_v3_v3v3(start_v, isect->next->p, gest->stk->points[0].p);
2057 sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
2060 angle = RAD2DEG(angle_v2v2(start_v, end_v));
2068 isect = isect->next;
2076 void sk_applyReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
2078 SK_Intersection *isect;
2080 for (isect = gest->intersections.first; isect; isect = isect->next)
2082 /* only reverse strokes that are crossed twice */
2083 if (isect->next && isect->next->stroke == isect->stroke)
2085 sk_reverseStroke(isect->stroke);
2088 isect = isect->next;
2093 int sk_detectConvertGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
2095 if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
2102 void sk_applyConvertGesture(bContext *C, SK_Gesture *UNUSED(gest), SK_Sketch *sketch)
2104 sk_convert(C, sketch);
2107 static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2109 gest->intersections.first = gest->intersections.last = NULL;
2110 gest->self_intersections.first = gest->self_intersections.last = NULL;
2112 gest->segments = sk_createStroke();
2113 gest->stk = sketch->gesture;
2115 gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
2116 gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
2117 gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
2120 static void sk_freeGesture(SK_Gesture *gest)
2122 sk_freeStroke(gest->segments);
2123 BLI_freelistN(&gest->intersections);
2124 BLI_freelistN(&gest->self_intersections);
2127 static void sk_applyGesture(bContext *C, SK_Sketch *sketch)
2130 SK_GestureAction *act;
2132 sk_initGesture(C, &gest, sketch);
2134 /* detect and apply */
2135 for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
2137 if (act->detect(C, &gest, sketch))
2139 act->apply(C, &gest, sketch);
2144 sk_freeGesture(&gest);
2147 /********************************************/
2150 static int sk_selectStroke(bContext *C, SK_Sketch *sketch, short mval[2], int extend)
2154 unsigned int buffer[MAXPICKBUF];
2157 view3d_set_viewcontext(C, &vc);
2159 rect.xmin= mval[0]-5;
2160 rect.xmax= mval[0]+5;
2161 rect.ymin= mval[1]-5;
2162 rect.ymax= mval[1]+5;
2164 hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
2168 int besthitresult = -1;
2171 besthitresult = buffer[3];
2174 besthitresult = buffer[3];
2175 /* loop and get best hit */
2178 if (besthitresult > 0)
2180 SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
2184 sk_selectAllSketch(sketch, -1);
2186 selected_stk->selected = 1;
2190 selected_stk->selected ^= 1;
2201 static void sk_queueRedrawSketch(SK_Sketch *sketch)
2203 if (sketch->active_stroke != NULL)
2205 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2210 // allqueue(REDRAWVIEW3D, 0);
2215 static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, int with_names)
2217 ToolSettings *ts= scene->toolsettings;
2220 glClear(GL_DEPTH_BUFFER_BIT);
2221 glEnable(GL_DEPTH_TEST);
2226 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
2228 sk_drawStroke(stk, id, NULL, -1, -1);
2235 float selected_rgb[3] = {1, 0, 0};
2236 float unselected_rgb[3] = {1, 0.5, 0};
2238 for (stk = sketch->strokes.first; stk; stk = stk->next)
2243 if (sk_hasOverdraw(sketch, stk))
2245 sk_adjustIndexes(sketch, &start, &end);
2248 sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
2250 if (stk->selected == 1)
2252 sk_drawStrokeSubdivision(ts, stk);
2256 if (sketch->active_stroke != NULL)
2258 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2260 if (ts->bone_sketching & BONE_SKETCHING_QUICK)
2262 sk_drawStrokeSubdivision(ts, sketch->active_stroke);
2267 GLUquadric *quad = gluNewQuadric();
2268 gluQuadricNormals(quad, GLU_SMOOTH);
2273 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2275 switch (sketch->next_point.mode)
2285 sk_drawPoint(quad, &sketch->next_point, 0.1);
2287 glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
2289 sk_drawEdge(quad, last, &sketch->next_point, 0.1);
2291 glDisable(GL_BLEND);
2295 gluDeleteQuadric(quad);
2301 if (sketch->depth_peels.first != NULL)
2303 float colors[8][3] = {
2314 GLUquadric *quad = gluNewQuadric();
2315 gluQuadricNormals(quad, GLU_SMOOTH);
2317 for (p = sketch->depth_peels.first; p; p = p->next)
2319 int index = GET_INT_FROM_POINTER(p->ob);
2320 index = (index >> 5) & 7;
2322 glColor3fv(colors[index]);
2324 glTranslatef(p->p[0], p->p[1], p->p[2]);
2325 gluSphere(quad, 0.02, 8, 8);
2329 gluDeleteQuadric(quad);
2333 glDisable(GL_DEPTH_TEST);
2335 /* only draw gesture in active area */
2336 if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
2338 float gesture_rgb[3] = {0, 0.5, 1};
2339 sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
2343 static int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
2345 ToolSettings *ts = CTX_data_tool_settings(C);
2347 if (sketch->active_stroke != NULL)
2349 SK_Stroke *stk = sketch->active_stroke;
2351 sk_endStroke(C, sketch);
2353 if (ts->bone_sketching & BONE_SKETCHING_QUICK)
2355 if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
2357 sk_retargetStroke(C, stk);
2361 sk_convertStroke(C, stk);
2364 // BIF_undo_push("Convert Sketch");
2365 sk_removeStroke(sketch, stk);
2367 // allqueue(REDRAWBUTSEDIT, 0);
2371 // allqueue(REDRAWVIEW3D, 0);
2378 static void sk_start_draw_stroke(SK_Sketch *sketch)
2380 if (sketch->active_stroke == NULL)
2382 sk_startStroke(sketch);
2383 sk_selectAllSketch(sketch, -1);
2385 sketch->active_stroke->selected = 1;
2389 static void sk_start_draw_gesture(SK_Sketch *sketch)
2391 sketch->gesture = sk_createStroke();
2394 static int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
2396 if (sk_stroke_filtermval(dd))
2398 sk_addStrokePoint(C, sketch, stk, dd, snap);
2399 sk_updateDrawData(dd);
2400 sk_updateNextPoint(sketch, stk);
2408 static int ValidSketchViewContext(ViewContext *vc)
2410 Object *obedit = vc->obedit;
2411 Scene *scene= vc->scene;
2414 obedit->type == OB_ARMATURE &&
2415 scene->toolsettings->bone_sketching & BONE_SKETCHING)
2425 int BDR_drawSketchNames(ViewContext *vc)
2427 if (ValidSketchViewContext(vc))
2429 SK_Sketch *sketch = viewcontextSketch(vc, 0);
2432 sk_drawSketch(vc->scene, vc->v3d, sketch, 1);
2440 void BDR_drawSketch(const bContext *C)
2442 if (ED_operator_sketch_mode(C))
2444 SK_Sketch *sketch = contextSketch(C, 0);
2447 sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), sketch, 0);
2452 static int sketch_delete(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
2454 SK_Sketch *sketch = contextSketch(C, 0);
2457 sk_deleteSelectedStrokes(sketch);
2458 // allqueue(REDRAWVIEW3D, 0);
2460 WM_event_add_notifier(C, NC_SCREEN|ND_SKETCH|NA_REMOVED, NULL);
2461 return OPERATOR_FINISHED;
2464 void BIF_sk_selectStroke(bContext *C, short mval[2], short extend)
2466 ToolSettings *ts = CTX_data_tool_settings(C);
2467 SK_Sketch *sketch = contextSketch(C, 0);
2469 if (sketch != NULL && ts->bone_sketching & BONE_SKETCHING)
2471 if (sk_selectStroke(C, sketch, mval, extend))
2472 ED_area_tag_redraw(CTX_wm_area(C));
2476 void BIF_convertSketch(bContext *C)
2478 if (ED_operator_sketch_full_mode(C))
2480 SK_Sketch *sketch = contextSketch(C, 0);
2483 sk_convert(C, sketch);
2484 // BIF_undo_push("Convert Sketch");
2485 // allqueue(REDRAWVIEW3D, 0);
2486 // allqueue(REDRAWBUTSEDIT, 0);
2491 void BIF_deleteSketch(bContext *C)
2493 if (ED_operator_sketch_full_mode(C))
2495 SK_Sketch *sketch = contextSketch(C, 0);
2498 sk_deleteSelectedStrokes(sketch);
2499 // BIF_undo_push("Convert Sketch");
2500 // allqueue(REDRAWVIEW3D, 0);
2506 void BIF_selectAllSketch(bContext *C, int mode)
2508 if (BIF_validSketchMode(C))
2510 SK_Sketch *sketch = contextSketch(C, 0);
2513 sk_selectAllSketch(sketch, mode);
2515 // allqueue(REDRAWVIEW3D, 0);
2521 SK_Sketch* contextSketch(const bContext *C, int create)
2523 Object *obedit = CTX_data_edit_object(C);
2524 SK_Sketch *sketch = NULL;
2526 if (obedit && obedit->type == OB_ARMATURE)
2528 bArmature *arm = obedit->data;
2530 if (arm->sketch == NULL && create)
2532 arm->sketch = createSketch();
2534 sketch = arm->sketch;
2540 SK_Sketch* viewcontextSketch(ViewContext *vc, int create)
2542 Object *obedit = vc->obedit;
2543 SK_Sketch *sketch = NULL;
2545 if (obedit && obedit->type == OB_ARMATURE)
2547 bArmature *arm = obedit->data;
2549 if (arm->sketch == NULL && create)
2551 arm->sketch = createSketch();
2553 sketch = arm->sketch;
2559 static int sketch_convert(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
2561 SK_Sketch *sketch = contextSketch(C, 0);
2564 sk_convert(C, sketch);
2565 ED_area_tag_redraw(CTX_wm_area(C));
2567 return OPERATOR_FINISHED;
2570 static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
2572 SK_Sketch *sketch = contextSketch(C, 0);
2575 sk_cancelStroke(sketch);
2576 ED_area_tag_redraw(CTX_wm_area(C));
2577 return OPERATOR_FINISHED;
2579 return OPERATOR_PASS_THROUGH;
2582 static int sketch_finish(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
2584 SK_Sketch *sketch = contextSketch(C, 0);
2587 if (sk_finish_stroke(C, sketch))
2589 ED_area_tag_redraw(CTX_wm_area(C));
2590 return OPERATOR_FINISHED;
2593 return OPERATOR_PASS_THROUGH;
2596 static int sketch_select(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
2598 SK_Sketch *sketch = contextSketch(C, 0);
2602 if (sk_selectStroke(C, sketch, event->mval, extend))
2603 ED_area_tag_redraw(CTX_wm_area(C));
2606 return OPERATOR_FINISHED;
2609 static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op)
2611 SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2612 sk_cancelStroke(sketch);
2613 MEM_freeN(op->customdata);
2614 return OPERATOR_CANCELLED;
2617 static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
2619 short snap = RNA_boolean_get(op->ptr, "snap");
2621 SK_Sketch *sketch = contextSketch(C, 1);
2623 op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
2624 sk_initDrawData(dd, event->mval);
2626 sk_start_draw_stroke(sketch);
2628 sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap);
2630 WM_event_add_modal_handler(C, op);
2632 return OPERATOR_RUNNING_MODAL;
2635 static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op)
2637 SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2638 sk_cancelStroke(sketch);
2639 MEM_freeN(op->customdata);
2640 return OPERATOR_CANCELLED;
2643 static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
2645 short snap = RNA_boolean_get(op->ptr, "snap");
2647 SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2648 sk_cancelStroke(sketch);
2650 op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
2651 sk_initDrawData(dd, event->mval);
2653 sk_start_draw_gesture(sketch);
2654 sk_draw_stroke(C, sketch, sketch->gesture, dd, snap);
2656 WM_event_add_modal_handler(C, op);
2658 return OPERATOR_RUNNING_MODAL;
2661 static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short gesture, SK_Stroke *stk)
2663 short snap = RNA_boolean_get(op->ptr, "snap");
2664 SK_DrawData *dd = op->customdata;
2665 SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2666 int retval = OPERATOR_RUNNING_MODAL;
2668 switch (event->type)
2673 RNA_boolean_set(op->ptr, "snap", snap);
2676 case INBETWEEN_MOUSEMOVE:
2677 dd->mval[0] = event->mval[0];
2678 dd->mval[1] = event->mval[1];
2679 sk_draw_stroke(C, sketch, stk, dd, snap);
2680 ED_area_tag_redraw(CTX_wm_area(C));
2683 op->type->cancel(C, op);
2684 ED_area_tag_redraw(CTX_wm_area(C));
2685 retval = OPERATOR_CANCELLED;
2688 if (event->val == KM_RELEASE)
2692 sk_endContinuousStroke(stk);
2693 sk_filterLastContinuousStroke(stk);
2694 sk_updateNextPoint(sketch, stk);
2695 ED_area_tag_redraw(CTX_wm_area(C));
2696 MEM_freeN(op->customdata);
2697 retval = OPERATOR_FINISHED;
2701 sk_endContinuousStroke(stk);
2702 sk_filterLastContinuousStroke(stk);
2704 if (stk->nb_points > 1)
2706 /* apply gesture here */
2707 sk_applyGesture(C, sketch);
2711 sketch->gesture = NULL;
2713 ED_area_tag_redraw(CTX_wm_area(C));
2714 MEM_freeN(op->customdata);
2715 retval = OPERATOR_FINISHED;
2724 static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
2726 SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2727 return sketch_draw_modal(C, op, event, 0, sketch->active_stroke);
2730 static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event)
2732 SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
2733 return sketch_draw_modal(C, op, event, 1, sketch->gesture);
2736 static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
2738 short snap = RNA_boolean_get(op->ptr, "snap");
2739 SK_Sketch *sketch = contextSketch(C, 0);
2745 sk_initDrawData(&dd, event->mval);
2746 sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, snap);
2747 ED_area_tag_redraw(CTX_wm_area(C));
2750 return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
2753 /* ============================================== Poll Functions ============================================= */
2755 int ED_operator_sketch_mode_active_stroke(bContext *C)
2757 ToolSettings *ts = CTX_data_tool_settings(C);
2758 SK_Sketch *sketch = contextSketch(C, 0);
2760 if (ts->bone_sketching & BONE_SKETCHING &&
2762 sketch->active_stroke != NULL)
2772 static int ED_operator_sketch_mode_gesture(bContext *C)
2774 ToolSettings *ts = CTX_data_tool_settings(C);
2775 SK_Sketch *sketch = contextSketch(C, 0);
2777 if (ts->bone_sketching & BONE_SKETCHING &&
2778 (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
2780 sketch->active_stroke == NULL)
2790 int ED_operator_sketch_full_mode(bContext *C)
2792 Object *obedit = CTX_data_edit_object(C);
2793 ToolSettings *ts = CTX_data_tool_settings(C);
2796 obedit->type == OB_ARMATURE &&
2797 ts->bone_sketching & BONE_SKETCHING &&
2798 (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0)
2808 int ED_operator_sketch_mode(const bContext *C)
2810 Object *obedit = CTX_data_edit_object(C);
2811 ToolSettings *ts = CTX_data_tool_settings(C);
2814 obedit->type == OB_ARMATURE &&
2815 ts->bone_sketching & BONE_SKETCHING)
2825 /* ================================================ Operators ================================================ */
2827 void SKETCH_OT_delete(wmOperatorType *ot)
2831 ot->idname= "SKETCH_OT_delete";
2834 ot->invoke= sketch_delete;
2836 ot->poll= ED_operator_sketch_full_mode;
2839 // ot->flag= OPTYPE_UNDO;
2842 void SKETCH_OT_select(wmOperatorType *ot)
2846 ot->idname= "SKETCH_OT_select";
2849 ot->invoke= sketch_select;
2851 ot->poll= ED_operator_sketch_full_mode;
2854 // ot->flag= OPTYPE_UNDO;
2857 void SKETCH_OT_cancel_stroke(wmOperatorType *ot)
2860 ot->name= "cancel stroke";
2861 ot->idname= "SKETCH_OT_cancel_stroke";
2864 ot->invoke= sketch_cancel;
2866 ot->poll= ED_operator_sketch_mode_active_stroke;
2869 // ot->flag= OPTYPE_UNDO;
2872 void SKETCH_OT_convert(wmOperatorType *ot)
2875 ot->name= "convert";
2876 ot->idname= "SKETCH_OT_convert";
2879 ot->invoke= sketch_convert;
2881 ot->poll= ED_operator_sketch_full_mode;
2884 ot->flag= OPTYPE_UNDO;
2887 void SKETCH_OT_finish_stroke(wmOperatorType *ot)
2890 ot->name= "end stroke";
2891 ot->idname= "SKETCH_OT_finish_stroke";
2894 ot->invoke= sketch_finish;
2896 ot->poll= ED_operator_sketch_mode_active_stroke;
2899 // ot->flag= OPTYPE_UNDO;
2902 void SKETCH_OT_draw_preview(wmOperatorType *ot)
2905 ot->name= "draw preview";
2906 ot->idname= "SKETCH_OT_draw_preview";
2909 ot->invoke= sketch_draw_preview;
2911 ot->poll= ED_operator_sketch_mode_active_stroke;
2913 RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
2916 // ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
2919 void SKETCH_OT_draw_stroke(wmOperatorType *ot)
2922 ot->name= "draw stroke";
2923 ot->idname= "SKETCH_OT_draw_stroke";
2926 ot->invoke = sketch_draw_stroke;
2927 ot->modal = sketch_draw_stroke_modal;
2928 ot->cancel = sketch_draw_stroke_cancel;
2930 ot->poll= (int (*)(bContext *))ED_operator_sketch_mode;
2932 RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
2935 ot->flag= OPTYPE_BLOCKING; // OPTYPE_REGISTER|OPTYPE_UNDO
2938 void SKETCH_OT_gesture(wmOperatorType *ot)
2941 ot->name= "gesture";
2942 ot->idname= "SKETCH_OT_gesture";
2945 ot->invoke = sketch_draw_gesture;
2946 ot->modal = sketch_draw_gesture_modal;
2947 ot->cancel = sketch_draw_gesture_cancel;
2949 ot->poll= ED_operator_sketch_mode_gesture;
2951 RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
2954 ot->flag= OPTYPE_BLOCKING; // OPTYPE_UNDO