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 *****
27 #include "MEM_guardedalloc.h"
29 #include "DNA_listBase.h"
30 #include "DNA_scene_types.h"
31 #include "DNA_screen_types.h"
32 #include "DNA_view3d_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_armature_types.h"
36 #include "DNA_userdef_types.h"
38 #include "BLI_blenlib.h"
39 #include "BLI_arithb.h"
40 #include "BLI_graph.h"
41 #include "BLI_ghash.h"
43 #include "BKE_utildefines.h"
44 #include "BKE_global.h"
45 #include "BKE_DerivedMesh.h"
46 #include "BKE_object.h"
48 #include "BKE_context.h"
50 #include "ED_view3d.h"
53 #include "UI_resources.h"
54 //#include "BIF_screen.h"
55 //#include "BIF_space.h"
56 //#include "BIF_mywindow.h"
57 #include "ED_armature.h"
58 #include "armature_intern.h"
59 //#include "BIF_sketch.h"
60 #include "BIF_retarget.h"
61 #include "BIF_generate.h"
62 //#include "BIF_interface.h"
64 #include "BIF_transform.h"
68 //#include "blendef.h"
69 //#include "mydevice.h"
84 typedef struct SK_Point
92 typedef struct SK_Stroke
94 struct SK_Stroke *next, *prev;
102 #define SK_OVERDRAW_LIMIT 5
104 typedef struct SK_Overdraw
111 #define SK_Stroke_BUFFER_INIT_SIZE 20
113 typedef struct SK_DrawData
116 short previous_mval[2];
120 typedef struct SK_Intersection
122 struct SK_Intersection *next, *prev;
128 float lambda; /* used for sorting intersection points */
131 typedef struct SK_Sketch
134 SK_Stroke *active_stroke;
140 typedef struct SK_StrokeIterator {
146 PreviousFct previous;
153 /*********************************/
160 typedef struct SK_Gesture {
164 ListBase intersections;
165 ListBase self_intersections;
167 int nb_self_intersections;
168 int nb_intersections;
172 typedef int (*GestureDetectFct)(bContext*, SK_Gesture*, SK_Sketch *);
173 typedef void (*GestureApplyFct)(bContext*, SK_Gesture*, SK_Sketch *);
175 typedef struct SK_GestureAction {
177 GestureDetectFct detect;
178 GestureApplyFct apply;
181 SK_Sketch *GLOBAL_sketch = NULL;
183 int LAST_SNAP_POINT_VALID = 0;
184 float LAST_SNAP_POINT[3];
186 /******************** PROTOTYPES ******************************/
188 void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
190 void sk_deleteSelectedStrokes(SK_Sketch *sketch);
192 void sk_freeStroke(SK_Stroke *stk);
193 void sk_freeSketch(SK_Sketch *sketch);
195 SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
197 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
198 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
199 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
200 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
201 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
202 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
203 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
204 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
205 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
206 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
207 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
208 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
209 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
210 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
213 void sk_resetOverdraw(SK_Sketch *sketch);
214 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
216 /******************** GESTURE ACTIONS ******************************/
218 SK_GestureAction GESTURE_ACTIONS[] =
220 {"Cut", sk_detectCutGesture, sk_applyCutGesture},
221 {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
222 {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
223 {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
224 {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
225 {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
226 {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
230 /******************** TEMPLATES UTILS *************************/
232 char *TEMPLATES_MENU = NULL;
233 int TEMPLATES_CURRENT = 0;
234 GHash *TEMPLATES_HASH = NULL;
235 RigGraph *TEMPLATE_RIGG = NULL;
237 void BIF_makeListTemplates(bContext *C)
239 Object *obedit = CTX_data_edit_object(C);
240 Scene *scene = CTX_data_scene(C);
244 if (TEMPLATES_HASH != NULL)
246 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
249 TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
250 TEMPLATES_CURRENT = 0;
252 for ( base = FIRSTBASE; base; base = base->next )
254 Object *ob = base->object;
256 if (ob != obedit && ob->type == OB_ARMATURE)
259 BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
261 if (ob == scene->toolsettings->skgen_template)
263 TEMPLATES_CURRENT = index;
269 char *BIF_listTemplates(bContext *C)
272 char menu_header[] = "Template%t|None%x0|";
275 if (TEMPLATES_MENU != NULL)
277 MEM_freeN(TEMPLATES_MENU);
280 TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
284 p += sprintf(TEMPLATES_MENU, "%s", menu_header);
286 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
288 while (!BLI_ghashIterator_isDone(&ghi))
290 Object *ob = BLI_ghashIterator_getValue(&ghi);
291 int key = (int)BLI_ghashIterator_getKey(&ghi);
293 p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
295 BLI_ghashIterator_step(&ghi);
298 return TEMPLATES_MENU;
301 int BIF_currentTemplate(bContext *C)
303 Scene *scene = CTX_data_scene(C);
304 if (TEMPLATES_CURRENT == 0 && scene->toolsettings->skgen_template != NULL)
307 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
309 while (!BLI_ghashIterator_isDone(&ghi))
311 Object *ob = BLI_ghashIterator_getValue(&ghi);
312 int key = (int)BLI_ghashIterator_getKey(&ghi);
314 if (ob == scene->toolsettings->skgen_template)
316 TEMPLATES_CURRENT = key;
320 BLI_ghashIterator_step(&ghi);
324 return TEMPLATES_CURRENT;
327 RigGraph* sk_makeTemplateGraph(bContext *C, Object *ob)
329 Object *obedit = CTX_data_edit_object(C);
337 if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
339 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
340 TEMPLATE_RIGG = NULL;
343 if (TEMPLATE_RIGG == NULL)
349 TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm);
353 return TEMPLATE_RIGG;
356 int BIF_nbJointsTemplate(bContext *C)
358 Scene *scene = CTX_data_scene(C);
359 RigGraph *rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
363 return RIG_nbJoints(rg);
371 char * BIF_nameBoneTemplate(bContext *C)
373 Scene *scene = CTX_data_scene(C);
374 SK_Sketch *stk = GLOBAL_sketch;
378 if (stk && stk->active_stroke != NULL)
380 index = stk->active_stroke->nb_points;
383 rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
390 return RIG_nameBone(rg, 0, index);
393 void BIF_freeTemplates(bContext *C)
395 if (TEMPLATES_MENU != NULL)
397 MEM_freeN(TEMPLATES_MENU);
398 TEMPLATES_MENU = NULL;
401 if (TEMPLATES_HASH != NULL)
403 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
404 TEMPLATES_HASH = NULL;
407 if (TEMPLATE_RIGG != NULL)
409 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
410 TEMPLATE_RIGG = NULL;
414 void BIF_setTemplate(bContext *C, int index)
416 Scene *scene = CTX_data_scene(C);
419 scene->toolsettings->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
423 scene->toolsettings->skgen_template = NULL;
425 if (TEMPLATE_RIGG != NULL)
427 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
429 TEMPLATE_RIGG = NULL;
433 /*********************** CONVERSION ***************************/
435 void sk_autoname(bContext *C, ReebArc *arc)
437 Scene *scene = CTX_data_scene(C);
438 if (scene->toolsettings->skgen_retarget_options & SK_RETARGET_AUTONAME)
442 char *num = scene->toolsettings->skgen_num_string;
445 BLI_snprintf(num, 8, "%i", i);
449 char *side = scene->toolsettings->skgen_side_string;
453 if (BLI_streq(side, ""))
457 else if (BLI_streq(side, "R") || BLI_streq(side, "L"))
462 else if (BLI_streq(side, "r") || BLI_streq(side, "l"))
470 if (arc->head->p[0] < 0)
472 BLI_snprintf(side, 8, caps?"R":"r");
476 BLI_snprintf(side, 8, caps?"L":"l");
483 ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
487 node = MEM_callocN(sizeof(ReebNode), "reeb node");
488 VECCOPY(node->p, pt->p);
489 Mat4MulVecfl(imat, node->p);
491 VECCOPY(node->no, pt->no);
492 Mat3MulVecfl(tmat, node->no);
497 ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
502 arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
503 arc->head = sk_pointToNode(stk->points, imat, tmat);
504 arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
506 arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
507 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
509 for (i = 0; i < arc->bcount; i++)
511 VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
512 Mat4MulVecfl(imat, arc->buckets[i].p);
514 VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
515 Mat3MulVecfl(tmat, arc->buckets[i].no);
521 void sk_retargetStroke(bContext *C, SK_Stroke *stk)
523 Scene *scene = CTX_data_scene(C);
524 Object *obedit = CTX_data_edit_object(C);
530 Mat4Invert(imat, obedit->obmat);
532 Mat3CpyMat4(tmat, obedit->obmat);
535 arc = sk_strokeToArc(stk, imat, tmat);
539 rg = sk_makeTemplateGraph(C, scene->toolsettings->skgen_template);
541 BIF_retargetArc(C, arc, rg);
543 sk_autoname(C, NULL);
545 MEM_freeN(arc->head);
546 MEM_freeN(arc->tail);
547 REEB_freeArc((BArc*)arc);
550 /**************************************************************/
552 void sk_freeSketch(SK_Sketch *sketch)
554 SK_Stroke *stk, *next;
556 for (stk = sketch->strokes.first; stk; stk = next)
566 SK_Sketch* sk_createSketch()
570 sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
572 sketch->active_stroke = NULL;
573 sketch->gesture = NULL;
575 sketch->strokes.first = NULL;
576 sketch->strokes.last = NULL;
581 void sk_initPoint(bContext *C, SK_Point *pt)
583 ARegion *ar = CTX_wm_region(C);
584 RegionView3D *rv3d = ar->regiondata;
586 VECCOPY(pt->no, rv3d->viewinv[2]);
588 /* more init code here */
591 void sk_copyPoint(SK_Point *dst, SK_Point *src)
593 memcpy(dst, src, sizeof(SK_Point));
596 void sk_allocStrokeBuffer(SK_Stroke *stk)
598 stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
601 void sk_freeStroke(SK_Stroke *stk)
603 MEM_freeN(stk->points);
607 SK_Stroke* sk_createStroke()
611 stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
615 stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
617 sk_allocStrokeBuffer(stk);
622 void sk_shrinkStrokeBuffer(SK_Stroke *stk)
624 if (stk->nb_points < stk->buf_size)
626 SK_Point *old_points = stk->points;
628 stk->buf_size = stk->nb_points;
630 sk_allocStrokeBuffer(stk);
632 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
634 MEM_freeN(old_points);
638 void sk_growStrokeBuffer(SK_Stroke *stk)
640 if (stk->nb_points == stk->buf_size)
642 SK_Point *old_points = stk->points;
646 sk_allocStrokeBuffer(stk);
648 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
650 MEM_freeN(old_points);
654 void sk_growStrokeBufferN(SK_Stroke *stk, int n)
656 if (stk->nb_points + n > stk->buf_size)
658 SK_Point *old_points = stk->points;
660 while (stk->nb_points + n > stk->buf_size)
665 sk_allocStrokeBuffer(stk);
667 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
669 MEM_freeN(old_points);
674 void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
676 memcpy(stk->points + n, pt, sizeof(SK_Point));
679 void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
681 int size = stk->nb_points - n;
683 sk_growStrokeBuffer(stk);
685 memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
687 memcpy(stk->points + n, pt, sizeof(SK_Point));
692 void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
694 sk_growStrokeBuffer(stk);
696 memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
701 void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
703 int size = end - start + 1;
705 sk_growStrokeBufferN(stk, len - size);
709 int tail_size = stk->nb_points - end + 1;
711 memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
714 memcpy(stk->points + start, pts, len * sizeof(SK_Point));
716 stk->nb_points += len - size;
719 void sk_trimStroke(SK_Stroke *stk, int start, int end)
721 int size = end - start + 1;
725 memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
728 stk->nb_points = size;
731 void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
734 SK_Point *prev, *next;
740 VecSubf(delta_p, p_end, p_start);
742 prev = stk->points + start;
743 next = stk->points + end;
745 VECCOPY(pt1.p, p_start);
746 VECCOPY(pt1.no, prev->no);
747 pt1.mode = prev->mode;
748 pt1.type = prev->type;
750 VECCOPY(pt2.p, p_end);
751 VECCOPY(pt2.no, next->no);
752 pt2.mode = next->mode;
753 pt2.type = next->type;
755 sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
756 sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
758 for (i = 1; i < total; i++)
760 float delta = (float)i / (float)total;
761 float *p = stk->points[start + 1 + i].p;
765 VecAddf(p, p, p_start);
769 void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
774 /* find first exact points outside of range */
775 for (;start > 0; start--)
777 if (stk->points[start].type == PT_EXACT)
783 for (;end < stk->nb_points - 1; end++)
785 if (stk->points[end].type == PT_EXACT)
793 for (i = start + 1; i < end; i++)
795 if (stk->points[i].type == PT_EXACT)
799 memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
806 /* some points were removes, move end of array */
809 int size = stk->nb_points - end;
810 memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
811 stk->nb_points = offset + size;
815 void sk_flattenStroke(SK_Stroke *stk, int start, int end)
817 float normal[3], distance[3];
821 total = end - start + 1;
823 VECCOPY(normal, stk->points[start].no);
825 VecSubf(distance, stk->points[end].p, stk->points[start].p);
826 Projf(normal, distance, normal);
827 limit = Normalize(normal);
829 for (i = 1; i < total - 1; i++)
831 float d = limit * i / total;
833 float *p = stk->points[start + i].p;
835 VecSubf(distance, p, stk->points[start].p);
836 Projf(distance, distance, normal);
838 VECCOPY(offset, normal);
841 VecSubf(p, p, distance);
842 VecAddf(p, p, offset);
846 void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
848 if (sketch->active_stroke == stk)
850 sketch->active_stroke = NULL;
853 BLI_remlink(&sketch->strokes, stk);
857 void sk_reverseStroke(SK_Stroke *stk)
859 SK_Point *old_points = stk->points;
862 sk_allocStrokeBuffer(stk);
864 for (i = 0; i < stk->nb_points; i++)
866 sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
869 MEM_freeN(old_points);
873 void sk_cancelStroke(SK_Sketch *sketch)
875 if (sketch->active_stroke != NULL)
877 sk_resetOverdraw(sketch);
878 sk_removeStroke(sketch, sketch->active_stroke);
882 /* Apply reverse Chaikin filter to simplify the polyline
884 void sk_filterStroke(SK_Stroke *stk, int start, int end)
886 SK_Point *old_points = stk->points;
887 int nb_points = stk->nb_points;
895 end = stk->nb_points - 1;
898 sk_allocStrokeBuffer(stk);
901 /* adding points before range */
902 for (i = 0; i < start; i++)
904 sk_appendStrokePoint(stk, old_points + i);
907 for (i = start, j = start; i <= end; i++)
914 sk_copyPoint(&pt, &old_points[j+1]);
920 VECCOPY(vec, old_points[j].p);
922 VecAddf(pt.p, pt.p, vec);
924 VECCOPY(vec, old_points[j+1].p);
926 VecAddf(pt.p, pt.p, vec);
928 VECCOPY(vec, old_points[j+2].p);
930 VecAddf(pt.p, pt.p, vec);
932 VECCOPY(vec, old_points[j+3].p);
934 VecAddf(pt.p, pt.p, vec);
936 sk_appendStrokePoint(stk, &pt);
941 /* this might be uneeded when filtering last continuous stroke */
942 if (old_points[i].type == PT_EXACT)
944 sk_appendStrokePoint(stk, old_points + i);
949 /* adding points after range */
950 for (i = end + 1; i < nb_points; i++)
952 sk_appendStrokePoint(stk, old_points + i);
955 MEM_freeN(old_points);
957 sk_shrinkStrokeBuffer(stk);
960 void sk_filterLastContinuousStroke(SK_Stroke *stk)
964 end = stk->nb_points -1;
966 for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
968 /* nothing to do here*/
973 sk_filterStroke(stk, start, end);
977 SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
981 if (stk->nb_points > 0)
983 pt = stk->points + (stk->nb_points - 1);
989 void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
998 glBegin(GL_LINE_STRIP);
1000 for (i = 0; i < stk->nb_points; i++)
1002 glVertex3fv(stk->points[i].p);
1010 float d_rgb[3] = {1, 1, 1};
1012 VECCOPY(rgb, color);
1013 VecSubf(d_rgb, d_rgb, rgb);
1014 VecMulf(d_rgb, 1.0f / (float)stk->nb_points);
1016 glBegin(GL_LINE_STRIP);
1018 for (i = 0; i < stk->nb_points; i++)
1020 if (i >= start && i <= end)
1022 glColor3f(0.3, 0.3, 0.3);
1028 glVertex3fv(stk->points[i].p);
1029 VecAddf(rgb, rgb, d_rgb);
1037 for (i = 0; i < stk->nb_points; i++)
1039 if (stk->points[i].type == PT_EXACT)
1041 glVertex3fv(stk->points[i].p);
1048 // glColor3f(1, 1, 1);
1049 // glBegin(GL_POINTS);
1051 // for (i = 0; i < stk->nb_points; i++)
1053 // if (stk->points[i].type == PT_CONTINUOUS)
1055 // glVertex3fv(stk->points[i].p);
1062 void drawSubdividedStrokeBy(bContext *C, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
1064 float head[3], tail[3];
1066 int end = iter->length;
1070 VECCOPY(head, iter->p);
1073 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2);
1076 index = next_subdividion(C, iter, bone_start, end, head, tail);
1081 VECCOPY(head, tail);
1082 bone_start = index; // start next bone from current index
1084 index = next_subdividion(C, iter, bone_start, end, head, tail);
1088 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
1091 void sk_drawStrokeSubdivision(bContext *C, SK_Stroke *stk)
1093 Scene *scene = CTX_data_scene(C);
1094 int head_index = -1;
1097 if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
1103 for (i = 0; i < stk->nb_points; i++)
1105 SK_Point *pt = stk->points + i;
1107 if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
1109 if (head_index == -1)
1115 if (i - head_index > 1)
1117 SK_StrokeIterator sk_iter;
1118 BArcIterator *iter = (BArcIterator*)&sk_iter;
1120 initStrokeIterator(iter, stk, head_index, i);
1122 if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1124 drawSubdividedStrokeBy(C, iter, nextAdaptativeSubdivision);
1126 else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1128 drawSubdividedStrokeBy(C, iter, nextLengthSubdivision);
1130 else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1132 drawSubdividedStrokeBy(C, iter, nextFixedSubdivision);
1143 SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts)
1145 ARegion *ar = CTX_wm_region(C);
1146 SK_Point *pt = NULL;
1149 for (i = 0; i < stk->nb_points; i++)
1151 if (all_pts || stk->points[i].type == PT_EXACT)
1156 project_short_noclip(ar, stk->points[i].p, pval);
1158 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1163 pt = stk->points + i;
1176 SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, short mval[2], int *dist)
1178 ARegion *ar = CTX_wm_region(C);
1179 SK_Point *pt = NULL;
1182 for (bone = ebones->first; bone; bone = bone->next)
1188 if ((bone->flag & BONE_CONNECTED) == 0)
1190 VECCOPY(vec, bone->head);
1191 Mat4MulVecfl(ob->obmat, vec);
1192 project_short_noclip(ar, vec, pval);
1194 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1200 VECCOPY(pt->p, vec);
1201 pt->type = PT_EXACT;
1206 VECCOPY(vec, bone->tail);
1207 Mat4MulVecfl(ob->obmat, vec);
1208 project_short_noclip(ar, vec, pval);
1210 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1216 VECCOPY(pt->p, vec);
1217 pt->type = PT_EXACT;
1224 void sk_resetOverdraw(SK_Sketch *sketch)
1226 sketch->over.target = NULL;
1227 sketch->over.start = -1;
1228 sketch->over.end = -1;
1229 sketch->over.count = 0;
1232 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
1234 return sketch->over.target &&
1235 sketch->over.count >= SK_OVERDRAW_LIMIT &&
1236 (sketch->over.target == stk || stk == NULL) &&
1237 (sketch->over.start != -1 || sketch->over.end != -1);
1240 void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1242 if (sketch->over.target == NULL)
1245 int closest_index = -1;
1246 int dist = SNAP_MIN_DISTANCE * 2;
1248 /* If snapping, don't start overdraw */
1249 if (sk_lastStrokePoint(stk)->mode == PT_SNAP)
1254 for (target = sketch->strokes.first; target; target = target->next)
1260 SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
1264 sketch->over.target = target;
1265 closest_index = index;
1270 if (sketch->over.target != NULL)
1272 if (closest_index > -1)
1274 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
1276 sketch->over.count = SK_OVERDRAW_LIMIT;
1280 sketch->over.count++;
1284 if (stk->nb_points == 1)
1286 sketch->over.start = closest_index;
1290 sketch->over.end = closest_index;
1294 else if (sketch->over.target != NULL)
1296 SK_Point *closest_pt = NULL;
1297 int dist = SNAP_MIN_DISTANCE * 2;
1300 closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
1302 if (closest_pt != NULL)
1304 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
1306 sketch->over.count = SK_OVERDRAW_LIMIT;
1310 sketch->over.count++;
1313 sketch->over.end = index;
1317 sketch->over.end = -1;
1322 /* return 1 on reverse needed */
1323 int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
1327 *start = sketch->over.start;
1328 *end = sketch->over.end;
1337 *end = sketch->over.target->nb_points - 1;
1351 void sk_endOverdraw(SK_Sketch *sketch)
1353 SK_Stroke *stk = sketch->active_stroke;
1355 if (sk_hasOverdraw(sketch, NULL))
1360 if (sk_adjustIndexes(sketch, &start, &end))
1362 sk_reverseStroke(stk);
1365 if (stk->nb_points > 1)
1367 stk->points->type = sketch->over.target->points[start].type;
1368 sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
1371 sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
1373 sk_removeStroke(sketch, stk);
1375 sk_resetOverdraw(sketch);
1380 void sk_startStroke(SK_Sketch *sketch)
1382 SK_Stroke *stk = sk_createStroke();
1384 BLI_addtail(&sketch->strokes, stk);
1385 sketch->active_stroke = stk;
1387 sk_resetOverdraw(sketch);
1390 void sk_endStroke(bContext *C, SK_Sketch *sketch)
1392 Scene *scene = CTX_data_scene(C);
1393 sk_shrinkStrokeBuffer(sketch->active_stroke);
1395 if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
1397 sk_endOverdraw(sketch);
1400 sketch->active_stroke = NULL;
1403 void sk_updateDrawData(SK_DrawData *dd)
1405 dd->type = PT_CONTINUOUS;
1407 dd->previous_mval[0] = dd->mval[0];
1408 dd->previous_mval[1] = dd->mval[1];
1411 float sk_distanceDepth(bContext *C, float p1[3], float p2[3])
1413 ARegion *ar = CTX_wm_region(C);
1414 RegionView3D *rv3d = ar->regiondata;
1418 VecSubf(vec, p1, p2);
1420 Projf(vec, vec, rv3d->viewinv[2]);
1422 distance = VecLength(vec);
1424 if (Inpf(rv3d->viewinv[2], vec) > 0)
1432 void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance)
1434 ARegion *ar = CTX_wm_region(C);
1435 ScrArea *sa = CTX_wm_area(C);
1436 View3D *v3d = sa->spacedata.first;
1441 progress = VecLenf(stk->points[start].p, stk->points[start - 1].p);
1443 for (i = start; i <= end; i++)
1445 float ray_start[3], ray_normal[3];
1446 float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p);
1449 project_short_noclip(ar, stk->points[i].p, pval);
1450 viewray(ar, v3d, pval, ray_start, ray_normal);
1452 VecMulf(ray_normal, distance * progress / length);
1453 VecAddf(stk->points[i].p, stk->points[i].p, ray_normal);
1459 void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd)
1461 ARegion *ar = CTX_wm_region(C);
1462 /* copied from grease pencil, need fixing */
1463 SK_Point *last = sk_lastStrokePoint(stk);
1465 float fp[3] = {0, 0, 0};
1470 VECCOPY(fp, last->p);
1473 initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
1475 /* method taken from editview.c - mouse_cursor() */
1476 project_short_noclip(ar, fp, cval);
1477 window_to_3d(ar, dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
1478 VecSubf(vec, fp, dvec);
1481 int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1483 pt->type = dd->type;
1484 pt->mode = PT_PROJECT;
1485 sk_projectDrawPoint(C, pt->p, stk, dd);
1490 int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1494 sk_initPoint(C, &pt);
1496 sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd);
1498 sk_appendStrokePoint(stk, &pt);
1503 int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1505 Scene *scene = CTX_data_scene(C);
1506 int point_added = 0;
1508 if (scene->snap_mode == SCE_SNAP_MODE_VOLUME)
1510 ListBase depth_peels;
1512 float *last_p = NULL;
1513 float dist = FLT_MAX;
1516 depth_peels.first = depth_peels.last = NULL;
1518 peelObjectsContext(C, &depth_peels, dd->mval);
1520 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
1522 last_p = stk->points[stk->nb_points - 1].p;
1524 else if (LAST_SNAP_POINT_VALID)
1526 last_p = LAST_SNAP_POINT;
1530 for (p1 = depth_peels.first; p1; p1 = p1->next)
1540 /* if peeling objects, take the first and last from each object */
1541 if (scene->snap_flag & SCE_SNAP_PEEL_OBJECT)
1544 for (peel = p1->next; peel; peel = peel->next)
1546 if (peel->ob == p1->ob)
1553 /* otherwise, pair first with second and so on */
1556 for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
1558 /* nothing to do here */
1566 VecAddf(vec, p1->p, p2->p);
1571 VECCOPY(vec, p1->p);
1581 new_dist = VecLenf(last_p, vec);
1583 if (new_dist < dist)
1591 if (dist != FLT_MAX)
1593 pt->type = dd->type;
1600 BLI_freelistN(&depth_peels);
1604 SK_Stroke *snap_stk;
1608 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
1610 /* snap to strokes */
1611 // if (scene->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
1612 for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
1614 SK_Point *spt = NULL;
1615 if (snap_stk == stk)
1617 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
1621 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
1626 VECCOPY(pt->p, spt->p);
1631 /* try to snap to closer object */
1632 found = snapObjectsContext(C, dd->mval, &dist, vec, no, SNAP_NOT_SELECTED);
1635 pt->type = dd->type;
1637 VECCOPY(pt->p, vec);
1646 int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1651 sk_initPoint(C, &pt);
1653 point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
1658 float length, distance;
1662 VECCOPY(final_p, pt.p);
1664 sk_projectDrawPoint(C, pt.p, stk, dd);
1665 sk_appendStrokePoint(stk, &pt);
1667 /* update all previous point to give smooth Z progresion */
1670 for (i = stk->nb_points - 2; i > 0; i--)
1672 length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
1674 if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
1682 distance = sk_distanceDepth(C, final_p, stk->points[i].p);
1684 sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
1687 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1695 void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
1697 Scene *scene = CTX_data_scene(C);
1698 int point_added = 0;
1702 point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
1705 if (point_added == 0)
1707 point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
1710 if (scene->toolsettings->bone_sketching & BONE_SKETCHING_ADJUST)
1712 sk_updateOverdraw(C, sketch, stk, dd);
1716 void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short qual)
1718 int point_added = 0;
1722 point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
1723 LAST_SNAP_POINT_VALID = 1;
1724 VECCOPY(LAST_SNAP_POINT, pt->p);
1728 LAST_SNAP_POINT_VALID = 0;
1731 if (point_added == 0)
1733 point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
1737 void sk_endContinuousStroke(SK_Stroke *stk)
1739 stk->points[stk->nb_points - 1].type = PT_EXACT;
1742 void sk_updateNextPoint(SK_Sketch *sketch)
1744 if (sketch->active_stroke)
1746 SK_Stroke *stk = sketch->active_stroke;
1747 memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
1751 int sk_stroke_filtermval(SK_DrawData *dd)
1754 if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist)
1762 void sk_initDrawData(SK_DrawData *dd)
1765 // getmouseco_areawin(dd->mval);
1766 dd->previous_mval[0] = -1;
1767 dd->previous_mval[1] = -1;
1768 dd->type = PT_EXACT;
1770 /********************************************/
1772 static void* headPoint(void *arg);
1773 static void* tailPoint(void *arg);
1774 static void* nextPoint(void *arg);
1775 static void* nextNPoint(void *arg, int n);
1776 static void* peekPoint(void *arg, int n);
1777 static void* previousPoint(void *arg);
1778 static int iteratorStopped(void *arg);
1780 static void initIteratorFct(SK_StrokeIterator *iter)
1782 iter->head = headPoint;
1783 iter->tail = tailPoint;
1784 iter->peek = peekPoint;
1785 iter->next = nextPoint;
1786 iter->nextN = nextNPoint;
1787 iter->previous = previousPoint;
1788 iter->stopped = iteratorStopped;
1791 static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
1793 SK_Point *pt = NULL;
1795 if (index >= 0 && index < iter->length)
1797 pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
1810 void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
1812 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1814 initIteratorFct(iter);
1819 iter->start = start + 1;
1820 iter->end = end - 1;
1825 iter->start = start - 1;
1826 iter->end = end + 1;
1830 iter->length = iter->stride * (iter->end - iter->start + 1);
1836 static void* headPoint(void *arg)
1838 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1839 SK_Point *result = NULL;
1841 result = &(iter->stroke->points[iter->start - iter->stride]);
1842 iter->p = result->p;
1843 iter->no = result->no;
1848 static void* tailPoint(void *arg)
1850 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1851 SK_Point *result = NULL;
1853 result = &(iter->stroke->points[iter->end + iter->stride]);
1854 iter->p = result->p;
1855 iter->no = result->no;
1860 static void* nextPoint(void *arg)
1862 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1863 SK_Point *result = NULL;
1866 if (iter->index < iter->length)
1868 result = setIteratorValues(iter, iter->index);
1874 static void* nextNPoint(void *arg, int n)
1876 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1877 SK_Point *result = NULL;
1881 /* check if passed end */
1882 if (iter->index < iter->length)
1884 result = setIteratorValues(iter, iter->index);
1890 static void* peekPoint(void *arg, int n)
1892 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1893 SK_Point *result = NULL;
1894 int index = iter->index + n;
1896 /* check if passed end */
1897 if (index < iter->length)
1899 result = setIteratorValues(iter, index);
1905 static void* previousPoint(void *arg)
1907 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1908 SK_Point *result = NULL;
1910 if (iter->index > 0)
1913 result = setIteratorValues(iter, iter->index);
1919 static int iteratorStopped(void *arg)
1921 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1923 if (iter->index >= iter->length)
1933 void sk_convertStroke(bContext *C, SK_Stroke *stk)
1935 Object *obedit = CTX_data_edit_object(C);
1936 Scene *scene = CTX_data_scene(C);
1937 bArmature *arm = obedit->data;
1939 EditBone *parent = NULL;
1940 float invmat[4][4]; /* move in caller function */
1947 Mat4Invert(invmat, obedit->obmat);
1949 Mat3CpyMat4(tmat, obedit->obmat);
1952 for (i = 0; i < stk->nb_points; i++)
1954 SK_Point *pt = stk->points + i;
1956 if (pt->type == PT_EXACT)
1965 EditBone *bone = NULL;
1966 EditBone *new_parent;
1968 if (i - head_index > 1)
1970 SK_StrokeIterator sk_iter;
1971 BArcIterator *iter = (BArcIterator*)&sk_iter;
1973 initStrokeIterator(iter, stk, head_index, i);
1975 if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1977 bone = subdivideArcBy(C, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
1979 else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1981 bone = subdivideArcBy(C, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
1983 else if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1985 bone = subdivideArcBy(C, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
1991 bone = addEditBone(arm, "Bone");
1993 VECCOPY(bone->head, head->p);
1994 VECCOPY(bone->tail, pt->p);
1996 Mat4MulVecfl(invmat, bone->head);
1997 Mat4MulVecfl(invmat, bone->tail);
1998 setBoneRollFromNormal(bone, pt->no, invmat, tmat);
2002 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
2004 /* move to end of chain */
2005 while (bone->parent != NULL)
2007 bone = bone->parent;
2008 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
2013 bone->parent = parent;
2014 bone->flag |= BONE_CONNECTED;
2017 parent = new_parent;
2025 void sk_convert(bContext *C, SK_Sketch *sketch)
2027 Scene *scene = CTX_data_scene(C);
2030 for (stk = sketch->strokes.first; stk; stk = stk->next)
2032 if (stk->selected == 1)
2034 if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
2036 sk_retargetStroke(C, stk);
2040 sk_convertStroke(C, stk);
2043 // allqueue(REDRAWBUTSEDIT, 0);
2047 /******************* GESTURE *************************/
2050 /* returns the number of self intersections */
2051 int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
2053 ARegion *ar = CTX_wm_region(C);
2057 for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
2059 float s_p1[3] = {0, 0, 0};
2060 float s_p2[3] = {0, 0, 0};
2063 project_float(ar, gesture->points[s_i].p, s_p1);
2064 project_float(ar, gesture->points[s_i + 1].p, s_p2);
2066 /* start checking from second next, because two consecutive cannot intersect */
2067 for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
2069 float g_p1[3] = {0, 0, 0};
2070 float g_p2[3] = {0, 0, 0};
2074 project_float(ar, gesture->points[g_i].p, g_p1);
2075 project_float(ar, gesture->points[g_i + 1].p, g_p2);
2077 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
2079 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
2081 isect->gesture_index = g_i;
2082 isect->before = s_i;
2083 isect->after = s_i + 1;
2084 isect->stroke = gesture;
2086 VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
2087 VecMulf(isect->p, lambda);
2088 VecAddf(isect->p, isect->p, gesture->points[s_i].p);
2090 BLI_addtail(list, isect);
2100 int cmpIntersections(void *i1, void *i2)
2102 SK_Intersection *isect1 = i1, *isect2 = i2;
2104 if (isect1->stroke == isect2->stroke)
2106 if (isect1->before < isect2->before)
2110 else if (isect1->before > isect2->before)
2116 if (isect1->lambda < isect2->lambda)
2120 else if (isect1->lambda > isect2->lambda)
2131 /* returns the maximum number of intersections per stroke */
2132 int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
2134 ARegion *ar = CTX_wm_region(C);
2135 ScrArea *sa = CTX_wm_area(C);
2136 View3D *v3d = sa->spacedata.first;
2140 for (stk = sketch->strokes.first; stk; stk = stk->next)
2145 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
2147 float s_p1[3] = {0, 0, 0};
2148 float s_p2[3] = {0, 0, 0};
2151 project_float(ar, stk->points[s_i].p, s_p1);
2152 project_float(ar, stk->points[s_i + 1].p, s_p2);
2154 for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
2156 float g_p1[3] = {0, 0, 0};
2157 float g_p2[3] = {0, 0, 0};
2161 project_float(ar, gesture->points[g_i].p, g_p1);
2162 project_float(ar, gesture->points[g_i + 1].p, g_p2);
2164 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
2166 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
2167 float ray_start[3], ray_end[3];
2170 isect->gesture_index = g_i;
2171 isect->before = s_i;
2172 isect->after = s_i + 1;
2173 isect->stroke = stk;
2174 isect->lambda = lambda;
2176 mval[0] = (short)(vi[0]);
2177 mval[1] = (short)(vi[1]);
2178 viewline(ar, v3d, mval, ray_start, ray_end);
2180 LineIntersectLine( stk->points[s_i].p,
2181 stk->points[s_i + 1].p,
2187 BLI_addtail(list, isect);
2194 added = MAX2(s_added, added);
2197 BLI_sortlist(list, cmpIntersections);
2202 int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
2204 SK_StrokeIterator sk_iter;
2205 BArcIterator *iter = (BArcIterator*)&sk_iter;
2207 float CORRELATION_THRESHOLD = 0.99f;
2211 sk_appendStrokePoint(segments, &gesture->points[0]);
2212 vec = segments->points[segments->nb_points - 1].p;
2214 initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
2216 for (i = 1, j = 0; i < gesture->nb_points; i++)
2220 /* Calculate normal */
2221 VecSubf(n, gesture->points[i].p, vec);
2223 if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
2226 sk_appendStrokePoint(segments, &gesture->points[j]);
2227 vec = segments->points[segments->nb_points - 1].p;
2228 segments->points[segments->nb_points - 1].type = PT_EXACT;
2232 sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
2234 return segments->nb_points - 1;
2237 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2239 if (gest->nb_segments == 1 && gest->nb_intersections == 1)
2247 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2249 SK_Intersection *isect;
2251 for (isect = gest->intersections.first; isect; isect = isect->next)
2256 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
2257 VECCOPY(pt.p, isect->p);
2259 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
2263 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2265 if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
2270 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
2271 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
2273 angle = VecAngle2(s1, s2);
2275 if (angle > 60 && angle < 120)
2284 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2286 SK_Intersection *isect;
2289 VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
2291 for (isect = gest->intersections.first; isect; isect = isect->next)
2294 float stroke_dir[3];
2297 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
2298 VECCOPY(pt.p, isect->p);
2300 VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
2302 /* same direction, trim end */
2303 if (Inpf(stroke_dir, trim_dir) > 0)
2305 sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
2306 sk_trimStroke(isect->stroke, 0, isect->after);
2308 /* else, trim start */
2311 sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
2312 sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
2318 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2320 if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
2322 SK_Intersection *isect, *self_isect;
2324 /* get the the last intersection of the first pair */
2325 for( isect = gest->intersections.first; isect; isect = isect->next )
2327 if (isect->stroke == isect->next->stroke)
2329 isect = isect->next;
2334 self_isect = gest->self_intersections.first;
2336 if (isect && isect->gesture_index < self_isect->gesture_index)
2345 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2347 SK_Intersection *isect;
2351 // command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
2352 if(command < 1) return;
2354 for (isect = gest->intersections.first; isect; isect = isect->next)
2356 SK_Intersection *i2;
2360 if (i2 && i2->stroke == isect->stroke)
2365 sk_flattenStroke(isect->stroke, isect->before, i2->after);
2368 sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
2371 sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
2380 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2382 if (gest->nb_segments == 2 && gest->nb_intersections == 2)
2387 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
2388 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
2390 angle = VecAngle2(s1, s2);
2401 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2403 SK_Intersection *isect;
2405 for (isect = gest->intersections.first; isect; isect = isect->next)
2407 /* only delete strokes that are crossed twice */
2408 if (isect->next && isect->next->stroke == isect->stroke)
2410 isect = isect->next;
2412 sk_removeStroke(sketch, isect->stroke);
2417 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2419 ARegion *ar = CTX_wm_region(C);
2420 if (gest->nb_segments > 2 && gest->nb_intersections == 2)
2422 short start_val[2], end_val[2];
2425 project_short_noclip(ar, gest->stk->points[0].p, start_val);
2426 project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
2428 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
2430 /* if gesture is a circle */
2433 SK_Intersection *isect;
2435 /* check if it circled around an exact point */
2436 for (isect = gest->intersections.first; isect; isect = isect->next)
2438 /* only delete strokes that are crossed twice */
2439 if (isect->next && isect->next->stroke == isect->stroke)
2441 int start_index, end_index;
2444 start_index = MIN2(isect->after, isect->next->after);
2445 end_index = MAX2(isect->before, isect->next->before);
2447 for (i = start_index; i <= end_index; i++)
2449 if (isect->stroke->points[i].type == PT_EXACT)
2451 return 1; /* at least one exact point found, stop detect here */
2456 isect = isect->next;
2465 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2467 SK_Intersection *isect;
2469 /* check if it circled around an exact point */
2470 for (isect = gest->intersections.first; isect; isect = isect->next)
2472 /* only merge strokes that are crossed twice */
2473 if (isect->next && isect->next->stroke == isect->stroke)
2475 int start_index, end_index;
2478 start_index = MIN2(isect->after, isect->next->after);
2479 end_index = MAX2(isect->before, isect->next->before);
2481 for (i = start_index; i <= end_index; i++)
2483 /* if exact, switch to continuous */
2484 if (isect->stroke->points[i].type == PT_EXACT)
2486 isect->stroke->points[i].type = PT_CONTINUOUS;
2491 isect = isect->next;
2496 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2498 if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
2500 SK_Intersection *isect;
2502 /* check if it circled around an exact point */
2503 for (isect = gest->intersections.first; isect; isect = isect->next)
2505 /* only delete strokes that are crossed twice */
2506 if (isect->next && isect->next->stroke == isect->stroke)
2508 float start_v[3], end_v[3];
2511 if (isect->gesture_index < isect->next->gesture_index)
2513 VecSubf(start_v, isect->p, gest->stk->points[0].p);
2514 VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
2518 VecSubf(start_v, isect->next->p, gest->stk->points[0].p);
2519 VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
2522 angle = VecAngle2(start_v, end_v);
2530 isect = isect->next;
2538 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2540 SK_Intersection *isect;
2542 for (isect = gest->intersections.first; isect; isect = isect->next)
2544 /* only reverse strokes that are crossed twice */
2545 if (isect->next && isect->next->stroke == isect->stroke)
2547 sk_reverseStroke(isect->stroke);
2550 isect = isect->next;
2555 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2557 if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
2564 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2566 sk_convert(C, sketch);
2569 static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2571 gest->intersections.first = gest->intersections.last = NULL;
2572 gest->self_intersections.first = gest->self_intersections.last = NULL;
2574 gest->segments = sk_createStroke();
2575 gest->stk = sketch->gesture;
2577 gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
2578 gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
2579 gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
2582 static void sk_freeGesture(SK_Gesture *gest)
2584 sk_freeStroke(gest->segments);
2585 BLI_freelistN(&gest->intersections);
2586 BLI_freelistN(&gest->self_intersections);
2589 void sk_applyGesture(bContext *C, SK_Sketch *sketch)
2592 SK_GestureAction *act;
2594 sk_initGesture(C, &gest, sketch);
2596 /* detect and apply */
2597 for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
2599 if (act->detect(C, &gest, sketch))
2601 act->apply(C, &gest, sketch);
2606 sk_freeGesture(&gest);
2609 /********************************************/
2611 void sk_deleteSelectedStrokes(SK_Sketch *sketch)
2613 SK_Stroke *stk, *next;
2615 for (stk = sketch->strokes.first; stk; stk = next)
2619 if (stk->selected == 1)
2621 sk_removeStroke(sketch, stk);
2626 void sk_selectAllSketch(SK_Sketch *sketch, int mode)
2628 SK_Stroke *stk = NULL;
2632 for (stk = sketch->strokes.first; stk; stk = stk->next)
2639 for (stk = sketch->strokes.first; stk; stk = stk->next)
2648 for (stk = sketch->strokes.first; stk; stk = stk->next)
2650 selected &= stk->selected;
2655 for (stk = sketch->strokes.first; stk; stk = stk->next)
2657 stk->selected = selected;
2662 void sk_selectStroke(SK_Sketch *sketch, short mval[2], int extend)
2664 unsigned int buffer[MAXPICKBUF];
2671 hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-5, mval[1]-5, mval[0]+5, mval[1]+5);
2673 hits = view3d_opengl_select(buffer, MAXPICKBUF, mval[0]-12, mval[1]-12, mval[0]+12, mval[1]+12);
2677 int besthitresult = -1;
2680 besthitresult = buffer[3];
2683 besthitresult = buffer[3];
2684 /* loop and get best hit */
2687 if (besthitresult > 0)
2689 SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
2693 sk_selectAllSketch(sketch, -1);
2695 selected_stk->selected = 1;
2699 selected_stk->selected ^= 1;
2708 void sk_queueRedrawSketch(SK_Sketch *sketch)
2710 if (sketch->active_stroke != NULL)
2712 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2717 // allqueue(REDRAWVIEW3D, 0);
2722 void sk_drawSketch(bContext *C, SK_Sketch *sketch, int with_names)
2724 Scene *scene = CTX_data_scene(C);
2728 glDisable(GL_DEPTH_TEST);
2730 glLineWidth(UI_GetThemeValuef(TH_VERTEX_SIZE));
2731 glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
2736 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
2738 sk_drawStroke(stk, id, NULL, -1, -1);
2745 float selected_rgb[3] = {1, 0, 0};
2746 float unselected_rgb[3] = {1, 0.5, 0};
2748 for (stk = sketch->strokes.first; stk; stk = stk->next)
2753 if (sk_hasOverdraw(sketch, stk))
2755 sk_adjustIndexes(sketch, &start, &end);
2758 sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
2760 if (stk->selected == 1)
2762 sk_drawStrokeSubdivision(C, stk);
2766 /* only draw gesture in active area */
2767 if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
2769 float gesture_rgb[3] = {0, 0.5, 1};
2770 sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
2773 if (sketch->active_stroke != NULL)
2775 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2777 if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2779 sk_drawStrokeSubdivision(C, sketch->active_stroke);
2784 /* update point if in active area */
2785 if (1 /*area_is_active_area(G.vd->area)*/)
2789 sk_initDrawData(&dd);
2790 sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, qual);
2793 glEnable(GL_LINE_STIPPLE);
2794 glColor3fv(selected_rgb);
2795 glBegin(GL_LINE_STRIP);
2797 glVertex3fv(last->p);
2798 glVertex3fv(sketch->next_point.p);
2802 glDisable(GL_LINE_STIPPLE);
2804 switch (sketch->next_point.mode)
2816 glVertex3fv(sketch->next_point.p);
2826 glEnable(GL_DEPTH_TEST);
2829 int sk_paint(bContext *C, SK_Sketch *sketch, short mbut)
2831 Scene *scene = CTX_data_scene(C);
2835 if (mbut == LEFTMOUSE)
2838 if (sketch->active_stroke == NULL)
2840 sk_startStroke(sketch);
2841 sk_selectAllSketch(sketch, -1);
2843 sketch->active_stroke->selected = 1;
2846 sk_initDrawData(&dd);
2850 /* get current user input */
2852 // getmouseco_areawin(dd.mval);
2854 /* only add current point to buffer if mouse moved (otherwise wait until it does) */
2855 if (sk_stroke_filtermval(&dd)) {
2857 sk_addStrokePoint(C, sketch, sketch->active_stroke, &dd, qual);
2858 sk_updateDrawData(&dd);
2864 // BIF_wait_for_statechange();
2867 // while( qtest() ) {
2868 // short event, val;
2869 // event = extern_qread(&val);
2872 /* do mouse checking at the end, so don't check twice, and potentially
2875 } while (0 /*get_mbut() & L_MOUSE*/);
2877 sk_endContinuousStroke(sketch->active_stroke);
2878 sk_filterLastContinuousStroke(sketch->active_stroke);
2879 sk_updateNextPoint(sketch);
2881 else if (mbut == RIGHTMOUSE)
2883 if (sketch->active_stroke != NULL)
2885 SK_Stroke *stk = sketch->active_stroke;
2887 sk_endStroke(C, sketch);
2889 if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2891 if (scene->toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
2893 sk_retargetStroke(C, stk);
2897 sk_convertStroke(C, stk);
2900 // BIF_undo_push("Convert Sketch");
2901 sk_removeStroke(sketch, stk);
2903 // allqueue(REDRAWBUTSEDIT, 0);
2907 // allqueue(REDRAWVIEW3D, 0);
2909 /* no gestures in quick mode */
2910 else if (scene->toolsettings->bone_sketching & BONE_SKETCHING_QUICK)
2912 retval = 0; /* return zero for default click behavior */
2917 sketch->gesture = sk_createStroke();
2919 sk_initDrawData(&dd);
2923 /* get current user input */
2925 // getmouseco_areawin(dd.mval);
2927 /* only add current point to buffer if mouse moved (otherwise wait until it does) */
2928 if (sk_stroke_filtermval(&dd)) {
2930 sk_addStrokeDrawPoint(C, sketch, sketch->gesture, &dd);
2931 sk_updateDrawData(&dd);
2933 /* draw only if mouse has moved */
2934 if (sketch->gesture->nb_points > 1)
2942 // BIF_wait_for_statechange();
2945 // while( qtest() ) {
2946 // short event, val;
2947 // event = extern_qread(&val);
2950 /* do mouse checking at the end, so don't check twice, and potentially
2953 } while (0 /*get_mbut() & R_MOUSE*/);
2955 sk_endContinuousStroke(sketch->gesture);
2956 sk_filterLastContinuousStroke(sketch->gesture);
2957 sk_filterLastContinuousStroke(sketch->gesture);
2958 sk_filterLastContinuousStroke(sketch->gesture);
2960 if (sketch->gesture->nb_points > 1)
2962 /* apply gesture here */
2963 sk_applyGesture(C, sketch);
2966 sk_freeStroke(sketch->gesture);
2967 sketch->gesture = NULL;
2970 // allqueue(REDRAWVIEW3D, 0);
2977 void BDR_drawSketchNames(bContext *C)
2979 if (BIF_validSketchMode(C))
2981 if (GLOBAL_sketch != NULL)
2983 sk_drawSketch(C, GLOBAL_sketch, 1);
2988 void BDR_drawSketch(bContext *C)
2990 if (BIF_validSketchMode(C))
2992 if (GLOBAL_sketch != NULL)
2994 sk_drawSketch(C, GLOBAL_sketch, 0);
2999 void BIF_endStrokeSketch(bContext *C)
3001 if (BIF_validSketchMode(C))
3003 if (GLOBAL_sketch != NULL)
3005 sk_endStroke(C, GLOBAL_sketch);
3006 // allqueue(REDRAWVIEW3D, 0);
3011 void BIF_cancelStrokeSketch(bContext *C)
3013 if (BIF_validSketchMode(C))
3015 if (GLOBAL_sketch != NULL)
3017 sk_cancelStroke(GLOBAL_sketch);
3018 // allqueue(REDRAWVIEW3D, 0);