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 "RNA_define.h"
39 #include "RNA_access.h"
41 #include "BLI_blenlib.h"
42 #include "BLI_arithb.h"
43 #include "BLI_graph.h"
44 #include "BLI_ghash.h"
46 #include "BKE_utildefines.h"
47 #include "BKE_global.h"
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_object.h"
51 #include "BKE_context.h"
53 #include "ED_view3d.h"
54 #include "ED_screen.h"
57 #include "UI_resources.h"
58 //#include "BIF_screen.h"
59 //#include "BIF_space.h"
60 //#include "BIF_mywindow.h"
61 #include "ED_armature.h"
62 #include "armature_intern.h"
63 //#include "BIF_sketch.h"
64 #include "BIF_retarget.h"
65 #include "BIF_generate.h"
66 //#include "BIF_interface.h"
68 #include "ED_transform.h"
73 //#include "blendef.h"
74 //#include "mydevice.h"
89 typedef struct SK_Point
98 typedef struct SK_Stroke
100 struct SK_Stroke *next, *prev;
108 #define SK_OVERDRAW_LIMIT 5
110 typedef struct SK_Overdraw
117 #define SK_Stroke_BUFFER_INIT_SIZE 20
119 typedef struct SK_DrawData
122 short previous_mval[2];
126 typedef struct SK_Intersection
128 struct SK_Intersection *next, *prev;
134 float lambda; /* used for sorting intersection points */
137 typedef struct SK_Sketch
140 ListBase depth_peels;
141 SK_Stroke *active_stroke;
147 typedef struct SK_StrokeIterator {
153 PreviousFct previous;
161 /*********************************/
168 typedef struct SK_Gesture {
172 ListBase intersections;
173 ListBase self_intersections;
175 int nb_self_intersections;
176 int nb_intersections;
180 typedef int (*GestureDetectFct)(bContext*, SK_Gesture*, SK_Sketch *);
181 typedef void (*GestureApplyFct)(bContext*, SK_Gesture*, SK_Sketch *);
183 typedef struct SK_GestureAction {
185 GestureDetectFct detect;
186 GestureApplyFct apply;
189 SK_Sketch *GLOBAL_sketch = NULL;
191 int LAST_SNAP_POINT_VALID = 0;
192 float LAST_SNAP_POINT[3];
194 /******************** PROTOTYPES ******************************/
196 void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
198 void sk_deleteSelectedStrokes(SK_Sketch *sketch);
200 void sk_freeStroke(SK_Stroke *stk);
201 void sk_freeSketch(SK_Sketch *sketch);
203 SK_Point *sk_lastStrokePoint(SK_Stroke *stk);
205 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
206 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
207 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
208 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
209 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
210 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
211 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
212 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
213 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
214 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
215 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
216 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
217 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
218 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
221 void sk_resetOverdraw(SK_Sketch *sketch);
222 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
224 /******************** GESTURE ACTIONS ******************************/
226 SK_GestureAction GESTURE_ACTIONS[] =
228 {"Cut", sk_detectCutGesture, sk_applyCutGesture},
229 {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
230 {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
231 {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
232 {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
233 {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
234 {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
238 /******************** TEMPLATES UTILS *************************/
240 char *TEMPLATES_MENU = NULL;
241 int TEMPLATES_CURRENT = 0;
242 GHash *TEMPLATES_HASH = NULL;
243 RigGraph *TEMPLATE_RIGG = NULL;
245 void BIF_makeListTemplates(const bContext *C)
247 Object *obedit = CTX_data_edit_object(C);
248 Scene *scene = CTX_data_scene(C);
249 ToolSettings *ts = CTX_data_tool_settings(C);
253 if (TEMPLATES_HASH != NULL)
255 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
258 TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
259 TEMPLATES_CURRENT = 0;
261 for ( base = FIRSTBASE; base; base = base->next )
263 Object *ob = base->object;
265 if (ob != obedit && ob->type == OB_ARMATURE)
268 BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
270 if (ob == ts->skgen_template)
272 TEMPLATES_CURRENT = index;
278 char *BIF_listTemplates(const bContext *C)
281 char menu_header[] = "Template%t|None%x0|";
284 if (TEMPLATES_MENU != NULL)
286 MEM_freeN(TEMPLATES_MENU);
289 TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
293 p += sprintf(TEMPLATES_MENU, "%s", menu_header);
295 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
297 while (!BLI_ghashIterator_isDone(&ghi))
299 Object *ob = BLI_ghashIterator_getValue(&ghi);
300 int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
302 p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
304 BLI_ghashIterator_step(&ghi);
307 return TEMPLATES_MENU;
310 int BIF_currentTemplate(const bContext *C)
312 ToolSettings *ts = CTX_data_tool_settings(C);
314 if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL)
317 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
319 while (!BLI_ghashIterator_isDone(&ghi))
321 Object *ob = BLI_ghashIterator_getValue(&ghi);
322 int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
324 if (ob == ts->skgen_template)
326 TEMPLATES_CURRENT = key;
330 BLI_ghashIterator_step(&ghi);
334 return TEMPLATES_CURRENT;
337 RigGraph* sk_makeTemplateGraph(const bContext *C, Object *ob)
339 Object *obedit = CTX_data_edit_object(C);
347 if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
349 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
350 TEMPLATE_RIGG = NULL;
353 if (TEMPLATE_RIGG == NULL)
359 TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm);
363 return TEMPLATE_RIGG;
366 int BIF_nbJointsTemplate(const bContext *C)
368 ToolSettings *ts = CTX_data_tool_settings(C);
369 RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template);
373 return RIG_nbJoints(rg);
381 char * BIF_nameBoneTemplate(const bContext *C)
383 ToolSettings *ts = CTX_data_tool_settings(C);
384 SK_Sketch *stk = GLOBAL_sketch;
388 if (stk && stk->active_stroke != NULL)
390 index = stk->active_stroke->nb_points;
393 rg = sk_makeTemplateGraph(C, ts->skgen_template);
400 return RIG_nameBone(rg, 0, index);
403 void BIF_freeTemplates(bContext *C)
405 if (TEMPLATES_MENU != NULL)
407 MEM_freeN(TEMPLATES_MENU);
408 TEMPLATES_MENU = NULL;
411 if (TEMPLATES_HASH != NULL)
413 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
414 TEMPLATES_HASH = NULL;
417 if (TEMPLATE_RIGG != NULL)
419 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
420 TEMPLATE_RIGG = NULL;
424 void BIF_setTemplate(bContext *C, int index)
426 ToolSettings *ts = CTX_data_tool_settings(C);
429 ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
433 ts->skgen_template = NULL;
435 if (TEMPLATE_RIGG != NULL)
437 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
439 TEMPLATE_RIGG = NULL;
443 /*********************** CONVERSION ***************************/
445 void sk_autoname(bContext *C, ReebArc *arc)
447 ToolSettings *ts = CTX_data_tool_settings(C);
448 if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME)
452 char *num = ts->skgen_num_string;
455 BLI_snprintf(num, 8, "%i", i);
459 char *side = ts->skgen_side_string;
463 if (BLI_streq(side, ""))
467 else if (BLI_streq(side, "R") || BLI_streq(side, "L"))
472 else if (BLI_streq(side, "r") || BLI_streq(side, "l"))
480 if (arc->head->p[0] < 0)
482 BLI_snprintf(side, 8, caps?"R":"r");
486 BLI_snprintf(side, 8, caps?"L":"l");
493 ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
497 node = MEM_callocN(sizeof(ReebNode), "reeb node");
498 VECCOPY(node->p, pt->p);
499 Mat4MulVecfl(imat, node->p);
501 VECCOPY(node->no, pt->no);
502 Mat3MulVecfl(tmat, node->no);
507 ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
512 arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
513 arc->head = sk_pointToNode(stk->points, imat, tmat);
514 arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
516 arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
517 arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
519 for (i = 0; i < arc->bcount; i++)
521 VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
522 Mat4MulVecfl(imat, arc->buckets[i].p);
524 VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
525 Mat3MulVecfl(tmat, arc->buckets[i].no);
531 void sk_retargetStroke(bContext *C, SK_Stroke *stk)
533 ToolSettings *ts = CTX_data_tool_settings(C);
534 Object *obedit = CTX_data_edit_object(C);
540 Mat4Invert(imat, obedit->obmat);
542 Mat3CpyMat4(tmat, obedit->obmat);
545 arc = sk_strokeToArc(stk, imat, tmat);
549 rg = sk_makeTemplateGraph(C, ts->skgen_template);
551 BIF_retargetArc(C, arc, rg);
553 sk_autoname(C, NULL);
555 MEM_freeN(arc->head);
556 MEM_freeN(arc->tail);
557 REEB_freeArc((BArc*)arc);
560 /**************************************************************/
562 void sk_freeSketch(SK_Sketch *sketch)
564 SK_Stroke *stk, *next;
566 for (stk = sketch->strokes.first; stk; stk = next)
573 BLI_freelistN(&sketch->depth_peels);
578 SK_Sketch* sk_createSketch()
582 sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch");
584 sketch->active_stroke = NULL;
585 sketch->gesture = NULL;
587 sketch->strokes.first = NULL;
588 sketch->strokes.last = NULL;
593 void sk_initPoint(bContext *C, SK_Point *pt)
595 ARegion *ar = CTX_wm_region(C);
596 RegionView3D *rv3d = ar->regiondata;
598 VECCOPY(pt->no, rv3d->viewinv[2]);
600 /* more init code here */
603 void sk_copyPoint(SK_Point *dst, SK_Point *src)
605 memcpy(dst, src, sizeof(SK_Point));
608 void sk_allocStrokeBuffer(SK_Stroke *stk)
610 stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer");
613 void sk_freeStroke(SK_Stroke *stk)
615 MEM_freeN(stk->points);
619 SK_Stroke* sk_createStroke()
623 stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke");
627 stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE;
629 sk_allocStrokeBuffer(stk);
634 void sk_shrinkStrokeBuffer(SK_Stroke *stk)
636 if (stk->nb_points < stk->buf_size)
638 SK_Point *old_points = stk->points;
640 stk->buf_size = stk->nb_points;
642 sk_allocStrokeBuffer(stk);
644 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
646 MEM_freeN(old_points);
650 void sk_growStrokeBuffer(SK_Stroke *stk)
652 if (stk->nb_points == stk->buf_size)
654 SK_Point *old_points = stk->points;
658 sk_allocStrokeBuffer(stk);
660 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
662 MEM_freeN(old_points);
666 void sk_growStrokeBufferN(SK_Stroke *stk, int n)
668 if (stk->nb_points + n > stk->buf_size)
670 SK_Point *old_points = stk->points;
672 while (stk->nb_points + n > stk->buf_size)
677 sk_allocStrokeBuffer(stk);
679 memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points);
681 MEM_freeN(old_points);
686 void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
688 memcpy(stk->points + n, pt, sizeof(SK_Point));
691 void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n)
693 int size = stk->nb_points - n;
695 sk_growStrokeBuffer(stk);
697 memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point));
699 memcpy(stk->points + n, pt, sizeof(SK_Point));
704 void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt)
706 sk_growStrokeBuffer(stk);
708 memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point));
713 void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end)
715 int size = end - start + 1;
717 sk_growStrokeBufferN(stk, len - size);
721 int tail_size = stk->nb_points - end + 1;
723 memmove(stk->points + start + len, stk->points + end + 1, tail_size * sizeof(SK_Point));
726 memcpy(stk->points + start, pts, len * sizeof(SK_Point));
728 stk->nb_points += len - size;
731 void sk_trimStroke(SK_Stroke *stk, int start, int end)
733 int size = end - start + 1;
737 memmove(stk->points, stk->points + start, size * sizeof(SK_Point));
740 stk->nb_points = size;
743 void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3])
746 SK_Point *prev, *next;
752 VecSubf(delta_p, p_end, p_start);
754 prev = stk->points + start;
755 next = stk->points + end;
757 VECCOPY(pt1.p, p_start);
758 VECCOPY(pt1.no, prev->no);
759 pt1.mode = prev->mode;
760 pt1.type = prev->type;
762 VECCOPY(pt2.p, p_end);
763 VECCOPY(pt2.no, next->no);
764 pt2.mode = next->mode;
765 pt2.type = next->type;
767 sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */
768 sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */
770 for (i = 1; i < total; i++)
772 float delta = (float)i / (float)total;
773 float *p = stk->points[start + 1 + i].p;
777 VecAddf(p, p, p_start);
781 void sk_polygonizeStroke(SK_Stroke *stk, int start, int end)
786 /* find first exact points outside of range */
787 for (;start > 0; start--)
789 if (stk->points[start].type == PT_EXACT)
795 for (;end < stk->nb_points - 1; end++)
797 if (stk->points[end].type == PT_EXACT)
805 for (i = start + 1; i < end; i++)
807 if (stk->points[i].type == PT_EXACT)
811 memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point));
818 /* some points were removes, move end of array */
821 int size = stk->nb_points - end;
822 memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point));
823 stk->nb_points = offset + size;
827 void sk_flattenStroke(SK_Stroke *stk, int start, int end)
829 float normal[3], distance[3];
833 total = end - start + 1;
835 VECCOPY(normal, stk->points[start].no);
837 VecSubf(distance, stk->points[end].p, stk->points[start].p);
838 Projf(normal, distance, normal);
839 limit = Normalize(normal);
841 for (i = 1; i < total - 1; i++)
843 float d = limit * i / total;
845 float *p = stk->points[start + i].p;
847 VecSubf(distance, p, stk->points[start].p);
848 Projf(distance, distance, normal);
850 VECCOPY(offset, normal);
853 VecSubf(p, p, distance);
854 VecAddf(p, p, offset);
858 void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk)
860 if (sketch->active_stroke == stk)
862 sketch->active_stroke = NULL;
865 BLI_remlink(&sketch->strokes, stk);
869 void sk_reverseStroke(SK_Stroke *stk)
871 SK_Point *old_points = stk->points;
874 sk_allocStrokeBuffer(stk);
876 for (i = 0; i < stk->nb_points; i++)
878 sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i);
881 MEM_freeN(old_points);
885 void sk_cancelStroke(SK_Sketch *sketch)
887 if (sketch->active_stroke != NULL)
889 sk_resetOverdraw(sketch);
890 sk_removeStroke(sketch, sketch->active_stroke);
894 /* Apply reverse Chaikin filter to simplify the polyline
896 void sk_filterStroke(SK_Stroke *stk, int start, int end)
898 SK_Point *old_points = stk->points;
899 int nb_points = stk->nb_points;
907 end = stk->nb_points - 1;
910 sk_allocStrokeBuffer(stk);
913 /* adding points before range */
914 for (i = 0; i < start; i++)
916 sk_appendStrokePoint(stk, old_points + i);
919 for (i = start, j = start; i <= end; i++)
926 sk_copyPoint(&pt, &old_points[j+1]);
932 VECCOPY(vec, old_points[j].p);
934 VecAddf(pt.p, pt.p, vec);
936 VECCOPY(vec, old_points[j+1].p);
938 VecAddf(pt.p, pt.p, vec);
940 VECCOPY(vec, old_points[j+2].p);
942 VecAddf(pt.p, pt.p, vec);
944 VECCOPY(vec, old_points[j+3].p);
946 VecAddf(pt.p, pt.p, vec);
948 pt.size = -0.25 * old_points[j].size + 0.75 * old_points[j+1].size + 0.75 * old_points[j+2].size - 0.25 * old_points[j+3].size;
950 sk_appendStrokePoint(stk, &pt);
955 /* this might be uneeded when filtering last continuous stroke */
956 if (old_points[i].type == PT_EXACT)
958 sk_appendStrokePoint(stk, old_points + i);
963 /* adding points after range */
964 for (i = end + 1; i < nb_points; i++)
966 sk_appendStrokePoint(stk, old_points + i);
969 MEM_freeN(old_points);
971 sk_shrinkStrokeBuffer(stk);
974 void sk_filterLastContinuousStroke(SK_Stroke *stk)
978 end = stk->nb_points -1;
980 for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--)
982 /* nothing to do here*/
987 sk_filterStroke(stk, start, end);
991 SK_Point *sk_lastStrokePoint(SK_Stroke *stk)
995 if (stk->nb_points > 0)
997 pt = stk->points + (stk->nb_points - 1);
1003 float sk_clampPointSize(SK_Point *pt, float size)
1005 return MAX2(size * pt->size, size / 2);
1008 void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
1010 glTranslatef(pt->p[0], pt->p[1], pt->p[2]);
1011 gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
1014 void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float size)
1016 float vec1[3], vec2[3] = {0, 0, 1}, axis[3];
1017 float angle, length;
1019 VecSubf(vec1, pt1->p, pt0->p);
1020 length = Normalize(vec1);
1021 Crossf(axis, vec2, vec1);
1023 if (VecIsNull(axis))
1028 angle = NormalizedVecAngle2(vec2, vec1);
1030 glRotatef(angle * 180 / M_PI + 180, axis[0], axis[1], axis[2]);
1032 gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
1035 void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float height)
1037 float vec2[3] = {0, 0, 1}, axis[3];
1042 Crossf(axis, vec2, pt->no);
1044 if (VecIsNull(axis))
1049 angle = NormalizedVecAngle2(vec2, pt->no);
1051 glRotatef(angle * 180 / M_PI, axis[0], axis[1], axis[2]);
1054 gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
1059 void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
1063 GLUquadric *quad = gluNewQuadric();
1064 gluQuadricNormals(quad, GLU_SMOOTH);
1070 for (i = 0; i < stk->nb_points; i++)
1074 sk_drawPoint(quad, stk->points + i, 0.1);
1078 sk_drawEdge(quad, stk->points + i - 1, stk->points + i, 0.1);
1087 float d_rgb[3] = {1, 1, 1};
1089 VECCOPY(rgb, color);
1090 VecSubf(d_rgb, d_rgb, rgb);
1091 VecMulf(d_rgb, 1.0f / (float)stk->nb_points);
1093 for (i = 0; i < stk->nb_points; i++)
1095 SK_Point *pt = stk->points + i;
1099 if (pt->type == PT_EXACT)
1102 sk_drawPoint(quad, pt, 0.15);
1103 sk_drawNormal(quad, pt, 0.05, 0.9);
1106 if (i >= start && i <= end)
1108 glColor3f(0.3, 0.3, 0.3);
1115 if (pt->type != PT_EXACT)
1118 sk_drawPoint(quad, pt, 0.1);
1123 sk_drawEdge(quad, pt - 1, pt, 0.1);
1128 VecAddf(rgb, rgb, d_rgb);
1132 gluDeleteQuadric(quad);
1135 void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
1137 SK_Stroke *stk = ((SK_StrokeIterator*)iter)->stroke;
1138 float head[3], tail[3];
1140 int end = iter->length;
1142 GLUquadric *quad = gluNewQuadric();
1143 gluQuadricNormals(quad, GLU_SMOOTH);
1146 VECCOPY(head, iter->p);
1148 index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
1151 SK_Point *pt = stk->points + index;
1156 sk_drawPoint(quad, pt, 0.15);
1158 sk_drawNormal(quad, pt, 0.05, 0.9);
1162 VECCOPY(head, tail);
1163 bone_start = index; // start next bone from current index
1165 index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
1168 gluDeleteQuadric(quad);
1171 void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
1173 int head_index = -1;
1176 if (toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
1182 for (i = 0; i < stk->nb_points; i++)
1184 SK_Point *pt = stk->points + i;
1186 if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
1188 if (head_index == -1)
1194 if (i - head_index > 1)
1196 SK_StrokeIterator sk_iter;
1197 BArcIterator *iter = (BArcIterator*)&sk_iter;
1199 initStrokeIterator(iter, stk, head_index, i);
1201 if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
1203 drawSubdividedStrokeBy(toolsettings, iter, nextAdaptativeSubdivision);
1205 else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
1207 drawSubdividedStrokeBy(toolsettings, iter, nextLengthSubdivision);
1209 else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
1211 drawSubdividedStrokeBy(toolsettings, iter, nextFixedSubdivision);
1222 SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, short mval[2], int *dist, int *index, int all_pts)
1224 ARegion *ar = CTX_wm_region(C);
1225 SK_Point *pt = NULL;
1228 for (i = 0; i < stk->nb_points; i++)
1230 if (all_pts || stk->points[i].type == PT_EXACT)
1235 project_short_noclip(ar, stk->points[i].p, pval);
1237 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1242 pt = stk->points + i;
1255 SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, short mval[2], int *dist)
1257 ARegion *ar = CTX_wm_region(C);
1258 SK_Point *pt = NULL;
1261 for (bone = ebones->first; bone; bone = bone->next)
1267 if ((bone->flag & BONE_CONNECTED) == 0)
1269 VECCOPY(vec, bone->head);
1270 Mat4MulVecfl(ob->obmat, vec);
1271 project_short_noclip(ar, vec, pval);
1273 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1279 VECCOPY(pt->p, vec);
1280 pt->type = PT_EXACT;
1285 VECCOPY(vec, bone->tail);
1286 Mat4MulVecfl(ob->obmat, vec);
1287 project_short_noclip(ar, vec, pval);
1289 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
1295 VECCOPY(pt->p, vec);
1296 pt->type = PT_EXACT;
1303 void sk_resetOverdraw(SK_Sketch *sketch)
1305 sketch->over.target = NULL;
1306 sketch->over.start = -1;
1307 sketch->over.end = -1;
1308 sketch->over.count = 0;
1311 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
1313 return sketch->over.target &&
1314 sketch->over.count >= SK_OVERDRAW_LIMIT &&
1315 (sketch->over.target == stk || stk == NULL) &&
1316 (sketch->over.start != -1 || sketch->over.end != -1);
1319 void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1321 if (sketch->over.target == NULL)
1324 int closest_index = -1;
1325 int dist = SNAP_MIN_DISTANCE * 2;
1327 // /* If snapping, don't start overdraw */ Can't do that, snap is embed too now
1328 // if (sk_lastStrokePoint(stk)->mode == PT_SNAP)
1333 for (target = sketch->strokes.first; target; target = target->next)
1339 SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
1343 sketch->over.target = target;
1344 closest_index = index;
1349 if (sketch->over.target != NULL)
1351 if (closest_index > -1)
1353 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
1355 sketch->over.count = SK_OVERDRAW_LIMIT;
1359 sketch->over.count++;
1363 if (stk->nb_points == 1)
1365 sketch->over.start = closest_index;
1369 sketch->over.end = closest_index;
1373 else if (sketch->over.target != NULL)
1375 SK_Point *closest_pt = NULL;
1376 int dist = SNAP_MIN_DISTANCE * 2;
1379 closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
1381 if (closest_pt != NULL)
1383 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
1385 sketch->over.count = SK_OVERDRAW_LIMIT;
1389 sketch->over.count++;
1392 sketch->over.end = index;
1396 sketch->over.end = -1;
1401 /* return 1 on reverse needed */
1402 int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
1406 *start = sketch->over.start;
1407 *end = sketch->over.end;
1416 *end = sketch->over.target->nb_points - 1;
1430 void sk_endOverdraw(SK_Sketch *sketch)
1432 SK_Stroke *stk = sketch->active_stroke;
1434 if (sk_hasOverdraw(sketch, NULL))
1439 if (sk_adjustIndexes(sketch, &start, &end))
1441 sk_reverseStroke(stk);
1444 if (stk->nb_points > 1)
1446 stk->points->type = sketch->over.target->points[start].type;
1447 sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
1450 sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
1452 sk_removeStroke(sketch, stk);
1454 sk_resetOverdraw(sketch);
1459 void sk_startStroke(SK_Sketch *sketch)
1461 SK_Stroke *stk = sk_createStroke();
1463 BLI_addtail(&sketch->strokes, stk);
1464 sketch->active_stroke = stk;
1466 sk_resetOverdraw(sketch);
1469 void sk_endStroke(bContext *C, SK_Sketch *sketch)
1471 ToolSettings *ts = CTX_data_tool_settings(C);
1472 sk_shrinkStrokeBuffer(sketch->active_stroke);
1474 if (ts->bone_sketching & BONE_SKETCHING_ADJUST)
1476 sk_endOverdraw(sketch);
1479 sketch->active_stroke = NULL;
1482 void sk_updateDrawData(SK_DrawData *dd)
1484 dd->type = PT_CONTINUOUS;
1486 dd->previous_mval[0] = dd->mval[0];
1487 dd->previous_mval[1] = dd->mval[1];
1490 float sk_distanceDepth(bContext *C, float p1[3], float p2[3])
1492 ARegion *ar = CTX_wm_region(C);
1493 RegionView3D *rv3d = ar->regiondata;
1497 VecSubf(vec, p1, p2);
1499 Projf(vec, vec, rv3d->viewinv[2]);
1501 distance = VecLength(vec);
1503 if (Inpf(rv3d->viewinv[2], vec) > 0)
1511 void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance)
1513 ARegion *ar = CTX_wm_region(C);
1514 ScrArea *sa = CTX_wm_area(C);
1515 View3D *v3d = sa->spacedata.first;
1520 progress = VecLenf(stk->points[start].p, stk->points[start - 1].p);
1522 for (i = start; i <= end; i++)
1524 float ray_start[3], ray_normal[3];
1525 float delta = VecLenf(stk->points[i].p, stk->points[i + 1].p);
1528 project_short_noclip(ar, stk->points[i].p, pval);
1529 viewray(ar, v3d, pval, ray_start, ray_normal);
1531 VecMulf(ray_normal, distance * progress / length);
1532 VecAddf(stk->points[i].p, stk->points[i].p, ray_normal);
1538 void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd)
1540 ARegion *ar = CTX_wm_region(C);
1541 /* copied from grease pencil, need fixing */
1542 SK_Point *last = sk_lastStrokePoint(stk);
1544 float fp[3] = {0, 0, 0};
1549 VECCOPY(fp, last->p);
1552 initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
1554 /* method taken from editview.c - mouse_cursor() */
1555 project_short_noclip(ar, fp, cval);
1556 window_to_3d_delta(ar, dvec, cval[0] - dd->mval[0], cval[1] - dd->mval[1]);
1557 VecSubf(vec, fp, dvec);
1560 int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1562 pt->type = dd->type;
1563 pt->mode = PT_PROJECT;
1564 sk_projectDrawPoint(C, pt->p, stk, dd);
1569 int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1573 sk_initPoint(C, &pt);
1575 sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd);
1577 sk_appendStrokePoint(stk, &pt);
1582 int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1584 ToolSettings *ts = CTX_data_tool_settings(C);
1585 int point_added = 0;
1587 if (ts->snap_mode == SCE_SNAP_MODE_VOLUME)
1590 float *last_p = NULL;
1591 float dist = FLT_MAX;
1595 sketch->depth_peels.first = sketch->depth_peels.last = NULL;
1597 peelObjectsContext(C, &sketch->depth_peels, dd->mval);
1599 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
1601 last_p = stk->points[stk->nb_points - 1].p;
1603 else if (LAST_SNAP_POINT_VALID)
1605 last_p = LAST_SNAP_POINT;
1609 for (p1 = sketch->depth_peels.first; p1; p1 = p1->next)
1620 /* if peeling objects, take the first and last from each object */
1621 if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT)
1624 for (peel = p1->next; peel; peel = peel->next)
1626 if (peel->ob == p1->ob)
1633 /* otherwise, pair first with second and so on */
1636 for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
1638 /* nothing to do here */
1646 VecAddf(vec, p1->p, p2->p);
1648 new_size = VecLenf(p1->p, p2->p);
1652 VECCOPY(vec, p1->p);
1663 new_dist = VecLenf(last_p, vec);
1665 if (new_dist < dist)
1674 if (dist != FLT_MAX)
1676 pt->type = dd->type;
1678 pt->size = size / 2;
1684 //BLI_freelistN(&depth_peels);
1688 SK_Stroke *snap_stk;
1692 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
1694 /* snap to strokes */
1695 // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
1696 for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
1698 SK_Point *spt = NULL;
1699 if (snap_stk == stk)
1701 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
1705 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
1710 VECCOPY(pt->p, spt->p);
1715 /* try to snap to closer object */
1716 found = snapObjectsContext(C, dd->mval, &dist, vec, no, SNAP_NOT_SELECTED);
1719 pt->type = dd->type;
1721 VECCOPY(pt->p, vec);
1730 int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
1735 sk_initPoint(C, &pt);
1737 point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
1742 float length, distance;
1746 VECCOPY(final_p, pt.p);
1748 sk_projectDrawPoint(C, pt.p, stk, dd);
1749 sk_appendStrokePoint(stk, &pt);
1751 /* update all previous point to give smooth Z progresion */
1754 for (i = stk->nb_points - 2; i > 0; i--)
1756 length += VecLenf(stk->points[i].p, stk->points[i + 1].p);
1758 if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
1766 distance = sk_distanceDepth(C, final_p, stk->points[i].p);
1768 sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
1771 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
1779 void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
1781 ToolSettings *ts = CTX_data_tool_settings(C);
1782 int point_added = 0;
1786 point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
1789 if (point_added == 0)
1791 point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
1794 if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST)
1796 sk_updateOverdraw(C, sketch, stk, dd);
1800 void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
1802 int point_added = 0;
1806 point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
1807 LAST_SNAP_POINT_VALID = 1;
1808 VECCOPY(LAST_SNAP_POINT, pt->p);
1812 LAST_SNAP_POINT_VALID = 0;
1815 if (point_added == 0)
1817 point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
1821 void sk_endContinuousStroke(SK_Stroke *stk)
1823 stk->points[stk->nb_points - 1].type = PT_EXACT;
1826 void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk)
1830 memcpy(&sketch->next_point, stk->points[stk->nb_points - 1].p, sizeof(SK_Point));
1834 int sk_stroke_filtermval(SK_DrawData *dd)
1837 if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist)
1845 void sk_initDrawData(SK_DrawData *dd, short mval[2])
1847 dd->mval[0] = mval[0];
1848 dd->mval[1] = mval[1];
1849 dd->previous_mval[0] = -1;
1850 dd->previous_mval[1] = -1;
1851 dd->type = PT_EXACT;
1853 /********************************************/
1855 static void* headPoint(void *arg);
1856 static void* tailPoint(void *arg);
1857 static void* nextPoint(void *arg);
1858 static void* nextNPoint(void *arg, int n);
1859 static void* peekPoint(void *arg, int n);
1860 static void* previousPoint(void *arg);
1861 static int iteratorStopped(void *arg);
1863 static void initIteratorFct(SK_StrokeIterator *iter)
1865 iter->head = headPoint;
1866 iter->tail = tailPoint;
1867 iter->peek = peekPoint;
1868 iter->next = nextPoint;
1869 iter->nextN = nextNPoint;
1870 iter->previous = previousPoint;
1871 iter->stopped = iteratorStopped;
1874 static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
1876 SK_Point *pt = NULL;
1878 if (index >= 0 && index < iter->length)
1880 pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
1883 iter->size = pt->size;
1895 void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
1897 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1899 initIteratorFct(iter);
1904 iter->start = start + 1;
1905 iter->end = end - 1;
1910 iter->start = start - 1;
1911 iter->end = end + 1;
1915 iter->length = iter->stride * (iter->end - iter->start + 1);
1921 static void* headPoint(void *arg)
1923 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1924 SK_Point *result = NULL;
1926 result = &(iter->stroke->points[iter->start - iter->stride]);
1927 iter->p = result->p;
1928 iter->no = result->no;
1929 iter->size = result->size;
1934 static void* tailPoint(void *arg)
1936 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1937 SK_Point *result = NULL;
1939 result = &(iter->stroke->points[iter->end + iter->stride]);
1940 iter->p = result->p;
1941 iter->no = result->no;
1942 iter->size = result->size;
1947 static void* nextPoint(void *arg)
1949 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1950 SK_Point *result = NULL;
1953 if (iter->index < iter->length)
1955 result = setIteratorValues(iter, iter->index);
1961 static void* nextNPoint(void *arg, int n)
1963 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1964 SK_Point *result = NULL;
1968 /* check if passed end */
1969 if (iter->index < iter->length)
1971 result = setIteratorValues(iter, iter->index);
1977 static void* peekPoint(void *arg, int n)
1979 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1980 SK_Point *result = NULL;
1981 int index = iter->index + n;
1983 /* check if passed end */
1984 if (index < iter->length)
1986 result = setIteratorValues(iter, index);
1992 static void* previousPoint(void *arg)
1994 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
1995 SK_Point *result = NULL;
1997 if (iter->index > 0)
2000 result = setIteratorValues(iter, iter->index);
2006 static int iteratorStopped(void *arg)
2008 SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
2010 if (iter->index >= iter->length)
2020 void sk_convertStroke(bContext *C, SK_Stroke *stk)
2022 Object *obedit = CTX_data_edit_object(C);
2023 ToolSettings *ts = CTX_data_tool_settings(C);
2024 bArmature *arm = obedit->data;
2026 EditBone *parent = NULL;
2027 float invmat[4][4]; /* move in caller function */
2034 Mat4Invert(invmat, obedit->obmat);
2036 Mat3CpyMat4(tmat, obedit->obmat);
2039 for (i = 0; i < stk->nb_points; i++)
2041 SK_Point *pt = stk->points + i;
2043 if (pt->type == PT_EXACT)
2052 EditBone *bone = NULL;
2053 EditBone *new_parent;
2055 if (i - head_index > 1)
2057 SK_StrokeIterator sk_iter;
2058 BArcIterator *iter = (BArcIterator*)&sk_iter;
2060 initStrokeIterator(iter, stk, head_index, i);
2062 if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
2064 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
2066 else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
2068 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
2070 else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
2072 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
2078 bone = addEditBone(arm, "Bone");
2080 VECCOPY(bone->head, head->p);
2081 VECCOPY(bone->tail, pt->p);
2083 Mat4MulVecfl(invmat, bone->head);
2084 Mat4MulVecfl(invmat, bone->tail);
2085 setBoneRollFromNormal(bone, head->no, invmat, tmat);
2089 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
2091 /* move to end of chain */
2092 while (bone->parent != NULL)
2094 bone = bone->parent;
2095 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
2100 bone->parent = parent;
2101 bone->flag |= BONE_CONNECTED;
2104 parent = new_parent;
2112 void sk_convert(bContext *C, SK_Sketch *sketch)
2114 ToolSettings *ts = CTX_data_tool_settings(C);
2117 for (stk = sketch->strokes.first; stk; stk = stk->next)
2119 if (stk->selected == 1)
2121 if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
2123 sk_retargetStroke(C, stk);
2127 sk_convertStroke(C, stk);
2130 // allqueue(REDRAWBUTSEDIT, 0);
2134 /******************* GESTURE *************************/
2137 /* returns the number of self intersections */
2138 int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
2140 ARegion *ar = CTX_wm_region(C);
2144 for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
2146 float s_p1[3] = {0, 0, 0};
2147 float s_p2[3] = {0, 0, 0};
2150 project_float(ar, gesture->points[s_i].p, s_p1);
2151 project_float(ar, gesture->points[s_i + 1].p, s_p2);
2153 /* start checking from second next, because two consecutive cannot intersect */
2154 for (g_i = s_i + 2; 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");
2168 isect->gesture_index = g_i;
2169 isect->before = s_i;
2170 isect->after = s_i + 1;
2171 isect->stroke = gesture;
2173 VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
2174 VecMulf(isect->p, lambda);
2175 VecAddf(isect->p, isect->p, gesture->points[s_i].p);
2177 BLI_addtail(list, isect);
2187 int cmpIntersections(void *i1, void *i2)
2189 SK_Intersection *isect1 = i1, *isect2 = i2;
2191 if (isect1->stroke == isect2->stroke)
2193 if (isect1->before < isect2->before)
2197 else if (isect1->before > isect2->before)
2203 if (isect1->lambda < isect2->lambda)
2207 else if (isect1->lambda > isect2->lambda)
2218 /* returns the maximum number of intersections per stroke */
2219 int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
2221 ARegion *ar = CTX_wm_region(C);
2222 ScrArea *sa = CTX_wm_area(C);
2223 View3D *v3d = sa->spacedata.first;
2227 for (stk = sketch->strokes.first; stk; stk = stk->next)
2232 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
2234 float s_p1[3] = {0, 0, 0};
2235 float s_p2[3] = {0, 0, 0};
2238 project_float(ar, stk->points[s_i].p, s_p1);
2239 project_float(ar, stk->points[s_i + 1].p, s_p2);
2241 for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
2243 float g_p1[3] = {0, 0, 0};
2244 float g_p2[3] = {0, 0, 0};
2248 project_float(ar, gesture->points[g_i].p, g_p1);
2249 project_float(ar, gesture->points[g_i + 1].p, g_p2);
2251 if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
2253 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
2254 float ray_start[3], ray_end[3];
2257 isect->gesture_index = g_i;
2258 isect->before = s_i;
2259 isect->after = s_i + 1;
2260 isect->stroke = stk;
2261 isect->lambda = lambda;
2263 mval[0] = (short)(vi[0]);
2264 mval[1] = (short)(vi[1]);
2265 viewline(ar, v3d, mval, ray_start, ray_end);
2267 LineIntersectLine( stk->points[s_i].p,
2268 stk->points[s_i + 1].p,
2274 BLI_addtail(list, isect);
2281 added = MAX2(s_added, added);
2284 BLI_sortlist(list, cmpIntersections);
2289 int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
2291 SK_StrokeIterator sk_iter;
2292 BArcIterator *iter = (BArcIterator*)&sk_iter;
2294 float CORRELATION_THRESHOLD = 0.99f;
2298 sk_appendStrokePoint(segments, &gesture->points[0]);
2299 vec = segments->points[segments->nb_points - 1].p;
2301 initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
2303 for (i = 1, j = 0; i < gesture->nb_points; i++)
2307 /* Calculate normal */
2308 VecSubf(n, gesture->points[i].p, vec);
2310 if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
2313 sk_appendStrokePoint(segments, &gesture->points[j]);
2314 vec = segments->points[segments->nb_points - 1].p;
2315 segments->points[segments->nb_points - 1].type = PT_EXACT;
2319 sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
2321 return segments->nb_points - 1;
2324 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2326 if (gest->nb_segments == 1 && gest->nb_intersections == 1)
2334 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2336 SK_Intersection *isect;
2338 for (isect = gest->intersections.first; isect; isect = isect->next)
2343 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
2344 VECCOPY(pt.p, isect->p);
2345 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
2347 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
2351 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2353 if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
2358 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
2359 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
2361 angle = VecAngle2(s1, s2);
2363 if (angle > 60 && angle < 120)
2372 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2374 SK_Intersection *isect;
2377 VecSubf(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
2379 for (isect = gest->intersections.first; isect; isect = isect->next)
2382 float stroke_dir[3];
2385 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
2386 VECCOPY(pt.p, isect->p);
2387 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
2389 VecSubf(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
2391 /* same direction, trim end */
2392 if (Inpf(stroke_dir, trim_dir) > 0)
2394 sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
2395 sk_trimStroke(isect->stroke, 0, isect->after);
2397 /* else, trim start */
2400 sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
2401 sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
2407 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2409 if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
2411 SK_Intersection *isect, *self_isect;
2413 /* get the the last intersection of the first pair */
2414 for( isect = gest->intersections.first; isect; isect = isect->next )
2416 if (isect->stroke == isect->next->stroke)
2418 isect = isect->next;
2423 self_isect = gest->self_intersections.first;
2425 if (isect && isect->gesture_index < self_isect->gesture_index)
2434 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2436 SK_Intersection *isect;
2440 // command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
2441 if(command < 1) return;
2443 for (isect = gest->intersections.first; isect; isect = isect->next)
2445 SK_Intersection *i2;
2449 if (i2 && i2->stroke == isect->stroke)
2454 sk_flattenStroke(isect->stroke, isect->before, i2->after);
2457 sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
2460 sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
2469 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2471 if (gest->nb_segments == 2 && gest->nb_intersections == 2)
2476 VecSubf(s1, gest->segments->points[1].p, gest->segments->points[0].p);
2477 VecSubf(s2, gest->segments->points[2].p, gest->segments->points[1].p);
2479 angle = VecAngle2(s1, s2);
2490 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2492 SK_Intersection *isect;
2494 for (isect = gest->intersections.first; isect; isect = isect->next)
2496 /* only delete strokes that are crossed twice */
2497 if (isect->next && isect->next->stroke == isect->stroke)
2499 isect = isect->next;
2501 sk_removeStroke(sketch, isect->stroke);
2506 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2508 ARegion *ar = CTX_wm_region(C);
2509 if (gest->nb_segments > 2 && gest->nb_intersections == 2)
2511 short start_val[2], end_val[2];
2514 project_short_noclip(ar, gest->stk->points[0].p, start_val);
2515 project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
2517 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
2519 /* if gesture is a circle */
2522 SK_Intersection *isect;
2524 /* check if it circled around an exact point */
2525 for (isect = gest->intersections.first; isect; isect = isect->next)
2527 /* only delete strokes that are crossed twice */
2528 if (isect->next && isect->next->stroke == isect->stroke)
2530 int start_index, end_index;
2533 start_index = MIN2(isect->after, isect->next->after);
2534 end_index = MAX2(isect->before, isect->next->before);
2536 for (i = start_index; i <= end_index; i++)
2538 if (isect->stroke->points[i].type == PT_EXACT)
2540 return 1; /* at least one exact point found, stop detect here */
2545 isect = isect->next;
2554 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2556 SK_Intersection *isect;
2558 /* check if it circled around an exact point */
2559 for (isect = gest->intersections.first; isect; isect = isect->next)
2561 /* only merge strokes that are crossed twice */
2562 if (isect->next && isect->next->stroke == isect->stroke)
2564 int start_index, end_index;
2567 start_index = MIN2(isect->after, isect->next->after);
2568 end_index = MAX2(isect->before, isect->next->before);
2570 for (i = start_index; i <= end_index; i++)
2572 /* if exact, switch to continuous */
2573 if (isect->stroke->points[i].type == PT_EXACT)
2575 isect->stroke->points[i].type = PT_CONTINUOUS;
2580 isect = isect->next;
2585 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2587 if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
2589 SK_Intersection *isect;
2591 /* check if it circled around an exact point */
2592 for (isect = gest->intersections.first; isect; isect = isect->next)
2594 /* only delete strokes that are crossed twice */
2595 if (isect->next && isect->next->stroke == isect->stroke)
2597 float start_v[3], end_v[3];
2600 if (isect->gesture_index < isect->next->gesture_index)
2602 VecSubf(start_v, isect->p, gest->stk->points[0].p);
2603 VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
2607 VecSubf(start_v, isect->next->p, gest->stk->points[0].p);
2608 VecSubf(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
2611 angle = VecAngle2(start_v, end_v);
2619 isect = isect->next;
2627 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2629 SK_Intersection *isect;
2631 for (isect = gest->intersections.first; isect; isect = isect->next)
2633 /* only reverse strokes that are crossed twice */
2634 if (isect->next && isect->next->stroke == isect->stroke)
2636 sk_reverseStroke(isect->stroke);
2639 isect = isect->next;
2644 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2646 if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
2653 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2655 sk_convert(C, sketch);
2658 static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
2660 gest->intersections.first = gest->intersections.last = NULL;
2661 gest->self_intersections.first = gest->self_intersections.last = NULL;
2663 gest->segments = sk_createStroke();
2664 gest->stk = sketch->gesture;
2666 gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
2667 gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
2668 gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
2671 static void sk_freeGesture(SK_Gesture *gest)
2673 sk_freeStroke(gest->segments);
2674 BLI_freelistN(&gest->intersections);
2675 BLI_freelistN(&gest->self_intersections);
2678 void sk_applyGesture(bContext *C, SK_Sketch *sketch)
2681 SK_GestureAction *act;
2683 sk_initGesture(C, &gest, sketch);
2685 /* detect and apply */
2686 for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
2688 if (act->detect(C, &gest, sketch))
2690 act->apply(C, &gest, sketch);
2695 sk_freeGesture(&gest);
2698 /********************************************/
2700 void sk_deleteSelectedStrokes(SK_Sketch *sketch)
2702 SK_Stroke *stk, *next;
2704 for (stk = sketch->strokes.first; stk; stk = next)
2708 if (stk->selected == 1)
2710 sk_removeStroke(sketch, stk);
2715 void sk_selectAllSketch(SK_Sketch *sketch, int mode)
2717 SK_Stroke *stk = NULL;
2721 for (stk = sketch->strokes.first; stk; stk = stk->next)
2728 for (stk = sketch->strokes.first; stk; stk = stk->next)
2737 for (stk = sketch->strokes.first; stk; stk = stk->next)
2739 selected &= stk->selected;
2744 for (stk = sketch->strokes.first; stk; stk = stk->next)
2746 stk->selected = selected;
2751 void sk_selectStroke(bContext *C, SK_Sketch *sketch, short mval[2], int extend)
2755 unsigned int buffer[MAXPICKBUF];
2758 view3d_set_viewcontext(C, &vc);
2760 rect.xmin= mval[0]-5;
2761 rect.xmax= mval[0]+5;
2762 rect.ymin= mval[1]-5;
2763 rect.ymax= mval[1]+5;
2765 hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
2769 int besthitresult = -1;
2772 besthitresult = buffer[3];
2775 besthitresult = buffer[3];
2776 /* loop and get best hit */
2779 if (besthitresult > 0)
2781 SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
2785 sk_selectAllSketch(sketch, -1);
2787 selected_stk->selected = 1;
2791 selected_stk->selected ^= 1;
2799 void sk_queueRedrawSketch(SK_Sketch *sketch)
2801 if (sketch->active_stroke != NULL)
2803 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2808 // allqueue(REDRAWVIEW3D, 0);
2813 void sk_drawSketch(Scene *scene, View3D *v3d, SK_Sketch *sketch, int with_names)
2815 ToolSettings *ts= scene->toolsettings;
2818 glClear(GL_DEPTH_BUFFER_BIT);
2819 glEnable(GL_DEPTH_TEST);
2824 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
2826 sk_drawStroke(stk, id, NULL, -1, -1);
2833 float selected_rgb[3] = {1, 0, 0};
2834 float unselected_rgb[3] = {1, 0.5, 0};
2836 for (stk = sketch->strokes.first; stk; stk = stk->next)
2841 if (sk_hasOverdraw(sketch, stk))
2843 sk_adjustIndexes(sketch, &start, &end);
2846 sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
2848 if (stk->selected == 1)
2850 sk_drawStrokeSubdivision(ts, stk);
2854 if (sketch->active_stroke != NULL)
2856 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
2858 if (ts->bone_sketching & BONE_SKETCHING_QUICK)
2860 sk_drawStrokeSubdivision(ts, sketch->active_stroke);
2865 GLUquadric *quad = gluNewQuadric();
2866 gluQuadricNormals(quad, GLU_SMOOTH);
2871 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2873 switch (sketch->next_point.mode)
2883 sk_drawPoint(quad, &sketch->next_point, 0.1);
2885 glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
2887 sk_drawEdge(quad, last, &sketch->next_point, 0.1);
2889 glDisable(GL_BLEND);
2893 gluDeleteQuadric(quad);
2899 if (sketch->depth_peels.first != NULL)
2901 float colors[8][3] = {
2912 GLUquadric *quad = gluNewQuadric();
2913 gluQuadricNormals(quad, GLU_SMOOTH);
2915 for (p = sketch->depth_peels.first; p; p = p->next)
2917 int index = (int)(p->ob);
2918 index = (index >> 5) & 7;
2920 glColor3fv(colors[index]);
2922 glTranslatef(p->p[0], p->p[1], p->p[2]);
2923 gluSphere(quad, 0.02, 8, 8);
2927 gluDeleteQuadric(quad);
2931 glDisable(GL_DEPTH_TEST);
2933 /* only draw gesture in active area */
2934 if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
2936 float gesture_rgb[3] = {0, 0.5, 1};
2937 sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
2941 int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
2943 ToolSettings *ts = CTX_data_tool_settings(C);
2945 if (sketch->active_stroke != NULL)
2947 SK_Stroke *stk = sketch->active_stroke;
2949 sk_endStroke(C, sketch);
2951 if (ts->bone_sketching & BONE_SKETCHING_QUICK)
2953 if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
2955 sk_retargetStroke(C, stk);
2959 sk_convertStroke(C, stk);
2962 // BIF_undo_push("Convert Sketch");
2963 sk_removeStroke(sketch, stk);
2965 // allqueue(REDRAWBUTSEDIT, 0);
2969 // allqueue(REDRAWVIEW3D, 0);
2976 void sk_start_draw_stroke(SK_Sketch *sketch)
2978 if (sketch->active_stroke == NULL)
2980 sk_startStroke(sketch);
2981 sk_selectAllSketch(sketch, -1);
2983 sketch->active_stroke->selected = 1;
2987 void sk_start_draw_gesture(SK_Sketch *sketch)
2989 sketch->gesture = sk_createStroke();
2992 int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
2994 if (sk_stroke_filtermval(dd))
2996 sk_addStrokePoint(C, sketch, stk, dd, snap);
2997 sk_updateDrawData(dd);
2998 sk_updateNextPoint(sketch, stk);
3005 static int ValidSketchViewContext(ViewContext *vc)
3007 Object *obedit = vc->obedit;
3008 Scene *scene= vc->scene;
3011 obedit->type == OB_ARMATURE &&
3012 scene->toolsettings->bone_sketching & BONE_SKETCHING)
3022 int BDR_drawSketchNames(ViewContext *vc)
3024 if (ValidSketchViewContext(vc))
3026 if (GLOBAL_sketch != NULL)
3028 sk_drawSketch(vc->scene, vc->v3d, GLOBAL_sketch, 1);
3036 void BDR_drawSketch(const bContext *C)
3038 if (ED_operator_sketch_mode(C))
3040 if (GLOBAL_sketch != NULL)
3042 sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), GLOBAL_sketch, 0);
3047 static int sketch_delete(bContext *C, wmOperator *op, wmEvent *event)
3049 if (GLOBAL_sketch != NULL)
3051 sk_deleteSelectedStrokes(GLOBAL_sketch);
3052 // allqueue(REDRAWVIEW3D, 0);
3054 return OPERATOR_FINISHED;
3057 void BIF_sk_selectStroke(bContext *C, short mval[2], short extend)
3059 if (GLOBAL_sketch != NULL)
3061 sk_selectStroke(C, GLOBAL_sketch, mval, extend);
3065 void BIF_convertSketch(bContext *C)
3067 if (ED_operator_sketch_full_mode(C))
3069 if (GLOBAL_sketch != NULL)
3071 sk_convert(C, GLOBAL_sketch);
3072 // BIF_undo_push("Convert Sketch");
3073 // allqueue(REDRAWVIEW3D, 0);
3074 // allqueue(REDRAWBUTSEDIT, 0);
3079 void BIF_deleteSketch(bContext *C)
3081 if (ED_operator_sketch_full_mode(C))
3083 if (GLOBAL_sketch != NULL)
3085 sk_deleteSelectedStrokes(GLOBAL_sketch);
3086 // BIF_undo_push("Convert Sketch");
3087 // allqueue(REDRAWVIEW3D, 0);
3092 //void BIF_selectAllSketch(bContext *C, int mode)
3094 // if (BIF_validSketchMode(C))
3096 // if (GLOBAL_sketch != NULL)
3098 // sk_selectAllSketch(GLOBAL_sketch, mode);
3100 //// allqueue(REDRAWVIEW3D, 0);
3105 void BIF_freeSketch(bContext *C)
3107 if (GLOBAL_sketch != NULL)
3109 sk_freeSketch(GLOBAL_sketch);
3110 GLOBAL_sketch = NULL;
3114 static int sketch_cancel(bContext *C, wmOperator *op, wmEvent *event)
3116 if (GLOBAL_sketch != NULL)
3118 sk_cancelStroke(GLOBAL_sketch);
3119 ED_area_tag_redraw(CTX_wm_area(C));
3120 return OPERATOR_FINISHED;
3122 return OPERATOR_PASS_THROUGH;
3125 static int sketch_finish(bContext *C, wmOperator *op, wmEvent *event)
3127 if (GLOBAL_sketch != NULL)
3129 if (sk_finish_stroke(C, GLOBAL_sketch))
3131 ED_area_tag_redraw(CTX_wm_area(C));
3132 return OPERATOR_FINISHED;
3135 return OPERATOR_PASS_THROUGH;
3138 static int sketch_select(bContext *C, wmOperator *op, wmEvent *event)
3140 if (GLOBAL_sketch != NULL)
3143 sk_selectStroke(C, GLOBAL_sketch, event->mval, extend);
3144 ED_area_tag_redraw(CTX_wm_area(C));
3147 return OPERATOR_FINISHED;
3150 static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op)
3152 sk_cancelStroke(GLOBAL_sketch);
3153 MEM_freeN(op->customdata);
3154 return OPERATOR_CANCELLED;
3157 static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
3159 short snap = RNA_boolean_get(op->ptr, "snap");