Blender  V2.59
editarmature_sketch.c
Go to the documentation of this file.
00001 /*
00002  * $Id: editarmature_sketch.c 36933 2011-05-26 21:04:01Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <string.h>
00029 #include <math.h>
00030 #include <float.h>
00031 
00032 #include "MEM_guardedalloc.h"
00033 
00034 #include "DNA_object_types.h"
00035 #include "DNA_scene_types.h"
00036 #include "DNA_armature_types.h"
00037 
00038 #include "RNA_define.h"
00039 #include "RNA_access.h"
00040 
00041 #include "BLI_blenlib.h"
00042 #include "BLI_math.h"
00043 #include "BLI_utildefines.h"
00044 #include "BLI_graph.h"
00045 #include "BLI_ghash.h"
00046 
00047 #include "BKE_context.h"
00048 #include "BKE_sketch.h"
00049 
00050 #include "ED_view3d.h"
00051 #include "ED_screen.h"
00052 
00053 #include "BIF_gl.h"
00054 //#include "BIF_screen.h"
00055 //#include "BIF_space.h"
00056 //#include "BIF_mywindow.h"
00057 #include "ED_armature.h"
00058 #include "armature_intern.h"
00059 //#include "BIF_sketch.h"
00060 #include "BIF_retarget.h"
00061 #include "BIF_generate.h"
00062 //#include "BIF_interface.h"
00063 
00064 #include "ED_transform.h"
00065 
00066 #include "WM_api.h"
00067 #include "WM_types.h"
00068 
00069 //#include "blendef.h"
00070 //#include "mydevice.h"
00071 #include "reeb.h"
00072 
00073 
00074 
00075 typedef int  (*GestureDetectFct)(bContext*, SK_Gesture*, SK_Sketch *);
00076 typedef void (*GestureApplyFct)(bContext*, SK_Gesture*, SK_Sketch *);
00077 
00078 typedef struct SK_GestureAction {
00079         char name[64];
00080         GestureDetectFct        detect;
00081         GestureApplyFct         apply;
00082 } SK_GestureAction;
00083 
00084 #if 0 /* UNUSED 2.5 */
00085 static SK_Point boneSnap;
00086 #endif
00087 
00088 static int    LAST_SNAP_POINT_VALID = 0;
00089 static float  LAST_SNAP_POINT[3];
00090 
00091 
00092 typedef struct SK_StrokeIterator {
00093         HeadFct         head;
00094         TailFct         tail;
00095         PeekFct         peek;
00096         NextFct         next;
00097         NextNFct        nextN;
00098         PreviousFct     previous;
00099         StoppedFct      stopped;
00100 
00101         float *p, *no;
00102         float size;
00103 
00104         int length;
00105         int index;
00106         /*********************************/
00107         SK_Stroke *stroke;
00108         int start;
00109         int end;
00110         int stride;
00111 } SK_StrokeIterator;
00112 
00113 /******************** PROTOTYPES ******************************/
00114 
00115 void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end);
00116 
00117 int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00118 void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00119 int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00120 void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00121 int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00122 void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00123 int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00124 void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00125 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00126 void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00127 int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00128 void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00129 int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00130 void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch);
00131 
00132 SK_Sketch* contextSketch(const bContext *c, int create);
00133 SK_Sketch* viewcontextSketch(ViewContext *vc, int create);
00134 
00135 void sk_resetOverdraw(SK_Sketch *sketch);
00136 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk);
00137 
00138 /******************** GESTURE ACTIONS ******************************/
00139 
00140 static SK_GestureAction GESTURE_ACTIONS[] =
00141         {
00142                 {"Cut", sk_detectCutGesture, sk_applyCutGesture},
00143                 {"Trim", sk_detectTrimGesture, sk_applyTrimGesture},
00144                 {"Command", sk_detectCommandGesture, sk_applyCommandGesture},
00145                 {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture},
00146                 {"Merge", sk_detectMergeGesture, sk_applyMergeGesture},
00147                 {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture},
00148                 {"Convert", sk_detectConvertGesture, sk_applyConvertGesture},
00149                 {"", NULL, NULL}
00150         };
00151 
00152 /******************** TEMPLATES UTILS *************************/
00153 
00154 static char  *TEMPLATES_MENU = NULL;
00155 static int    TEMPLATES_CURRENT = 0;
00156 static GHash *TEMPLATES_HASH = NULL;
00157 static RigGraph *TEMPLATE_RIGG = NULL;
00158 
00159 void BIF_makeListTemplates(const bContext *C)
00160 {
00161         Object *obedit = CTX_data_edit_object(C);
00162         Scene *scene = CTX_data_scene(C);
00163         ToolSettings *ts = CTX_data_tool_settings(C);
00164         Base *base;
00165         int index = 0;
00166 
00167         if (TEMPLATES_HASH != NULL)
00168         {
00169                 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
00170         }
00171 
00172         TEMPLATES_HASH = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "makeListTemplates gh");
00173         TEMPLATES_CURRENT = 0;
00174 
00175         for ( base = FIRSTBASE; base; base = base->next )
00176         {
00177                 Object *ob = base->object;
00178 
00179                 if (ob != obedit && ob->type == OB_ARMATURE)
00180                 {
00181                         index++;
00182                         BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob);
00183 
00184                         if (ob == ts->skgen_template)
00185                         {
00186                                 TEMPLATES_CURRENT = index;
00187                         }
00188                 }
00189         }
00190 }
00191 
00192 char *BIF_listTemplates(const bContext *UNUSED(C))
00193 {
00194         GHashIterator ghi;
00195         char menu_header[] = "Template%t|None%x0|";
00196         char *p;
00197 
00198         if (TEMPLATES_MENU != NULL)
00199         {
00200                 MEM_freeN(TEMPLATES_MENU);
00201         }
00202 
00203         TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu");
00204 
00205         p = TEMPLATES_MENU;
00206 
00207         p += sprintf(TEMPLATES_MENU, "%s", menu_header);
00208 
00209         BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
00210 
00211         while (!BLI_ghashIterator_isDone(&ghi))
00212         {
00213                 Object *ob = BLI_ghashIterator_getValue(&ghi);
00214                 int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
00215 
00216                 p += sprintf(p, "|%s%%x%i", ob->id.name+2, key);
00217 
00218                 BLI_ghashIterator_step(&ghi);
00219         }
00220 
00221         return TEMPLATES_MENU;
00222 }
00223 
00224 int   BIF_currentTemplate(const bContext *C)
00225 {
00226         ToolSettings *ts = CTX_data_tool_settings(C);
00227 
00228         if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL)
00229         {
00230                 GHashIterator ghi;
00231                 BLI_ghashIterator_init(&ghi, TEMPLATES_HASH);
00232 
00233                 while (!BLI_ghashIterator_isDone(&ghi))
00234                 {
00235                         Object *ob = BLI_ghashIterator_getValue(&ghi);
00236                         int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi));
00237 
00238                         if (ob == ts->skgen_template)
00239                         {
00240                                 TEMPLATES_CURRENT = key;
00241                                 break;
00242                         }
00243 
00244                         BLI_ghashIterator_step(&ghi);
00245                 }
00246         }
00247 
00248         return TEMPLATES_CURRENT;
00249 }
00250 
00251 static RigGraph* sk_makeTemplateGraph(const bContext *C, Object *ob)
00252 {
00253         Object *obedit = CTX_data_edit_object(C);
00254         if (ob == obedit)
00255         {
00256                 return NULL;
00257         }
00258 
00259         if (ob != NULL)
00260         {
00261                 if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob)
00262                 {
00263                         RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
00264                         TEMPLATE_RIGG = NULL;
00265                 }
00266 
00267                 if (TEMPLATE_RIGG == NULL)
00268                 {
00269                         bArmature *arm;
00270 
00271                         arm = ob->data;
00272 
00273                         TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm);
00274                 }
00275         }
00276 
00277         return TEMPLATE_RIGG;
00278 }
00279 
00280 int BIF_nbJointsTemplate(const bContext *C)
00281 {
00282         ToolSettings *ts = CTX_data_tool_settings(C);
00283         RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template);
00284 
00285         if (rg)
00286         {
00287                 return RIG_nbJoints(rg);
00288         }
00289         else
00290         {
00291                 return -1;
00292         }
00293 }
00294 
00295 const char * BIF_nameBoneTemplate(const bContext *C)
00296 {
00297         ToolSettings *ts = CTX_data_tool_settings(C);
00298         SK_Sketch *stk = contextSketch(C, 1);
00299         RigGraph *rg;
00300         int index = 0;
00301 
00302         if (stk && stk->active_stroke != NULL)
00303         {
00304                 index = stk->active_stroke->nb_points;
00305         }
00306 
00307         rg = sk_makeTemplateGraph(C, ts->skgen_template);
00308 
00309         if (rg == NULL)
00310         {
00311                 return "";
00312         }
00313 
00314         return RIG_nameBone(rg, 0, index);
00315 }
00316 
00317 void  BIF_freeTemplates(bContext *UNUSED(C))
00318 {
00319         if (TEMPLATES_MENU != NULL)
00320         {
00321                 MEM_freeN(TEMPLATES_MENU);
00322                 TEMPLATES_MENU = NULL;
00323         }
00324 
00325         if (TEMPLATES_HASH != NULL)
00326         {
00327                 BLI_ghash_free(TEMPLATES_HASH, NULL, NULL);
00328                 TEMPLATES_HASH = NULL;
00329         }
00330 
00331         if (TEMPLATE_RIGG != NULL)
00332         {
00333                 RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
00334                 TEMPLATE_RIGG = NULL;
00335         }
00336 }
00337 
00338 void  BIF_setTemplate(bContext *C, int index)
00339 {
00340         ToolSettings *ts = CTX_data_tool_settings(C);
00341         if (index > 0)
00342         {
00343                 ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index));
00344         }
00345         else
00346         {
00347                 ts->skgen_template = NULL;
00348 
00349                 if (TEMPLATE_RIGG != NULL)
00350                 {
00351                         RIG_freeRigGraph((BGraph*)TEMPLATE_RIGG);
00352                 }
00353                 TEMPLATE_RIGG = NULL;
00354         }
00355 }
00356 
00357 /*********************** CONVERSION ***************************/
00358 
00359 static void sk_autoname(bContext *C, ReebArc *arc)
00360 {
00361         ToolSettings *ts = CTX_data_tool_settings(C);
00362         if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME)
00363         {
00364                 if (arc == NULL)
00365                 {
00366                         char *num = ts->skgen_num_string;
00367                         int i = atoi(num);
00368                         i++;
00369                         BLI_snprintf(num, 8, "%i", i);
00370                 }
00371                 else
00372                 {
00373                         char *side = ts->skgen_side_string;
00374                         int valid = 0;
00375                         int caps = 0;
00376 
00377                         if (side[0] == '\0')
00378                         {
00379                                 valid = 1;
00380                         }
00381                         else if (strcmp(side, "R")==0 || strcmp(side, "L")==0)
00382                         {
00383                                 valid = 1;
00384                                 caps = 1;
00385                         }
00386                         else if (strcmp(side, "r")==0 || strcmp(side, "l")==0)
00387                         {
00388                                 valid = 1;
00389                                 caps = 0;
00390                         }
00391 
00392                         if (valid)
00393                         {
00394                                 if (arc->head->p[0] < 0)
00395                                 {
00396                                         BLI_snprintf(side, 8, caps?"R":"r");
00397                                 }
00398                                 else
00399                                 {
00400                                         BLI_snprintf(side, 8, caps?"L":"l");
00401                                 }
00402                         }
00403                 }
00404         }
00405 }
00406 
00407 static ReebNode *sk_pointToNode(SK_Point *pt, float imat[][4], float tmat[][3])
00408 {
00409         ReebNode *node;
00410 
00411         node = MEM_callocN(sizeof(ReebNode), "reeb node");
00412         VECCOPY(node->p, pt->p);
00413         mul_m4_v3(imat, node->p);
00414 
00415         VECCOPY(node->no, pt->no);
00416         mul_m3_v3(tmat, node->no);
00417 
00418         return node;
00419 }
00420 
00421 static ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[][4], float tmat[][3])
00422 {
00423         ReebArc *arc;
00424         int i;
00425 
00426         arc = MEM_callocN(sizeof(ReebArc), "reeb arc");
00427         arc->head = sk_pointToNode(stk->points, imat, tmat);
00428         arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat);
00429 
00430         arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */
00431         arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets");
00432 
00433         for (i = 0; i < arc->bcount; i++)
00434         {
00435                 VECCOPY(arc->buckets[i].p, stk->points[i + 1].p);
00436                 mul_m4_v3(imat, arc->buckets[i].p);
00437 
00438                 VECCOPY(arc->buckets[i].no, stk->points[i + 1].no);
00439                 mul_m3_v3(tmat, arc->buckets[i].no);
00440         }
00441 
00442         return arc;
00443 }
00444 
00445 static void sk_retargetStroke(bContext *C, SK_Stroke *stk)
00446 {
00447         ToolSettings *ts = CTX_data_tool_settings(C);
00448         Object *obedit = CTX_data_edit_object(C);
00449         float imat[4][4];
00450         float tmat[3][3];
00451         ReebArc *arc;
00452         RigGraph *rg;
00453 
00454         invert_m4_m4(imat, obedit->obmat);
00455 
00456         copy_m3_m4(tmat, obedit->obmat);
00457         transpose_m3(tmat);
00458 
00459         arc = sk_strokeToArc(stk, imat, tmat);
00460 
00461         sk_autoname(C, arc);
00462 
00463         rg = sk_makeTemplateGraph(C, ts->skgen_template);
00464 
00465         BIF_retargetArc(C, arc, rg);
00466 
00467         sk_autoname(C, NULL);
00468 
00469         MEM_freeN(arc->head);
00470         MEM_freeN(arc->tail);
00471         REEB_freeArc((BArc*)arc);
00472 }
00473 
00474 /**************************************************************/
00475 
00476 static void sk_cancelStroke(SK_Sketch *sketch)
00477 {
00478         if (sketch->active_stroke != NULL)
00479         {
00480                 sk_resetOverdraw(sketch);
00481                 sk_removeStroke(sketch, sketch->active_stroke);
00482         }
00483 }
00484 
00485 
00486 static float sk_clampPointSize(SK_Point *pt, float size)
00487 {
00488         return MAX2(size * pt->size, size / 2);
00489 }
00490 
00491 static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
00492 {
00493         glTranslatef(pt->p[0], pt->p[1], pt->p[2]);
00494         gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
00495 }
00496 
00497 static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float size)
00498 {
00499         float vec1[3], vec2[3] = {0, 0, 1}, axis[3];
00500         float angle, length;
00501 
00502         sub_v3_v3v3(vec1, pt1->p, pt0->p);
00503         length = normalize_v3(vec1);
00504         cross_v3_v3v3(axis, vec2, vec1);
00505 
00506         if (is_zero_v3(axis))
00507         {
00508                 axis[1] = 1;
00509         }
00510 
00511         angle = angle_normalized_v3v3(vec2, vec1);
00512 
00513         glRotatef(angle * 180 / M_PI + 180, axis[0], axis[1], axis[2]);
00514 
00515         gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
00516 }
00517 
00518 static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float height)
00519 {
00520         float vec2[3] = {0, 0, 1}, axis[3];
00521         float angle;
00522         
00523         glPushMatrix();
00524 
00525         cross_v3_v3v3(axis, vec2, pt->no);
00526 
00527         if (is_zero_v3(axis))
00528         {
00529                 axis[1] = 1;
00530         }
00531 
00532         angle = angle_normalized_v3v3(vec2, pt->no);
00533 
00534         glRotatef(angle * 180 / M_PI, axis[0], axis[1], axis[2]);
00535 
00536         glColor3f(0, 1, 1);
00537         gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
00538 
00539         glPopMatrix();
00540 }
00541 
00542 static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
00543 {
00544         float rgb[3];
00545         int i;
00546         GLUquadric *quad = gluNewQuadric();
00547         gluQuadricNormals(quad, GLU_SMOOTH);
00548 
00549         if (id != -1)
00550         {
00551                 glLoadName(id);
00552 
00553                 for (i = 0; i < stk->nb_points; i++)
00554                 {
00555                         glPushMatrix();
00556 
00557                         sk_drawPoint(quad, stk->points + i, 0.1);
00558 
00559                         if (i > 0)
00560                         {
00561                                 sk_drawEdge(quad, stk->points + i - 1, stk->points + i, 0.1);
00562                         }
00563 
00564                         glPopMatrix();
00565                 }
00566 
00567         }
00568         else
00569         {
00570                 float d_rgb[3] = {1, 1, 1};
00571 
00572                 copy_v3_v3(rgb, color);
00573                 sub_v3_v3(d_rgb, rgb);
00574                 mul_v3_fl(d_rgb, 1.0f / (float)stk->nb_points);
00575 
00576                 for (i = 0; i < stk->nb_points; i++)
00577                 {
00578                         SK_Point *pt = stk->points + i;
00579 
00580                         glPushMatrix();
00581 
00582                         if (pt->type == PT_EXACT)
00583                         {
00584                                 glColor3f(0, 0, 0);
00585                                 sk_drawPoint(quad, pt, 0.15);
00586                                 sk_drawNormal(quad, pt, 0.05, 0.9);
00587                         }
00588 
00589                         if (i >= start && i <= end)
00590                         {
00591                                 glColor3f(0.3, 0.3, 0.3);
00592                         }
00593                         else
00594                         {
00595                                 glColor3fv(rgb);
00596                         }
00597 
00598                         if (pt->type != PT_EXACT)
00599                         {
00600 
00601                                 sk_drawPoint(quad, pt, 0.1);
00602                         }
00603 
00604                         if (i > 0)
00605                         {
00606                                 sk_drawEdge(quad, pt - 1, pt, 0.1);
00607                         }
00608 
00609                         glPopMatrix();
00610 
00611                         add_v3_v3(rgb, d_rgb);
00612                 }
00613         }
00614 
00615         gluDeleteQuadric(quad);
00616 }
00617 
00618 static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
00619 {
00620         SK_Stroke *stk = ((SK_StrokeIterator*)iter)->stroke;
00621         float head[3], tail[3];
00622         int bone_start = 0;
00623         int end = iter->length;
00624         int index;
00625         GLUquadric *quad = gluNewQuadric();
00626         gluQuadricNormals(quad, GLU_SMOOTH);
00627 
00628         iter->head(iter);
00629         VECCOPY(head, iter->p);
00630 
00631         index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
00632         while (index != -1)
00633         {
00634                 SK_Point *pt = stk->points + index;
00635 
00636                 glPushMatrix();
00637 
00638                 glColor3f(0, 1, 0);
00639                 sk_drawPoint(quad, pt, 0.15);
00640 
00641                 sk_drawNormal(quad, pt, 0.05, 0.9);
00642 
00643                 glPopMatrix();
00644 
00645                 VECCOPY(head, tail);
00646                 bone_start = index; // start next bone from current index
00647 
00648                 index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
00649         }
00650 
00651         gluDeleteQuadric(quad);
00652 }
00653 
00654 static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
00655 {
00656         int head_index = -1;
00657         int i;
00658 
00659         if (toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET)
00660         {
00661                 return;
00662         }
00663 
00664 
00665         for (i = 0; i < stk->nb_points; i++)
00666         {
00667                 SK_Point *pt = stk->points + i;
00668 
00669                 if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */
00670                 {
00671                         if (head_index == -1)
00672                         {
00673                                 head_index = i;
00674                         }
00675                         else
00676                         {
00677                                 if (i - head_index > 1)
00678                                 {
00679                                         SK_StrokeIterator sk_iter;
00680                                         BArcIterator *iter = (BArcIterator*)&sk_iter;
00681 
00682                                         initStrokeIterator(iter, stk, head_index, i);
00683 
00684                                         if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
00685                                         {
00686                                                 drawSubdividedStrokeBy(toolsettings, iter, nextAdaptativeSubdivision);
00687                                         }
00688                                         else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
00689                                         {
00690                                                 drawSubdividedStrokeBy(toolsettings, iter, nextLengthSubdivision);
00691                                         }
00692                                         else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
00693                                         {
00694                                                 drawSubdividedStrokeBy(toolsettings, iter, nextFixedSubdivision);
00695                                         }
00696 
00697                                 }
00698 
00699                                 head_index = i;
00700                         }
00701                 }
00702         }
00703 }
00704 
00705 static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], int *dist, int *index, int all_pts)
00706 {
00707         ARegion *ar = CTX_wm_region(C);
00708         SK_Point *pt = NULL;
00709         int i;
00710 
00711         for (i = 0; i < stk->nb_points; i++)
00712         {
00713                 if (all_pts || stk->points[i].type == PT_EXACT)
00714                 {
00715                         short pval[2];
00716                         int pdist;
00717 
00718                         project_short_noclip(ar, stk->points[i].p, pval);
00719 
00720                         pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
00721 
00722                         if (pdist < *dist)
00723                         {
00724                                 *dist = pdist;
00725                                 pt = stk->points + i;
00726 
00727                                 if (index != NULL)
00728                                 {
00729                                         *index = i;
00730                                 }
00731                         }
00732                 }
00733         }
00734 
00735         return pt;
00736 }
00737 
00738 #if 0 /* UNUSED 2.5 */
00739 static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, int mval[2], int *dist)
00740 {
00741         ARegion *ar = CTX_wm_region(C);
00742         SK_Point *pt = NULL;
00743         EditBone *bone;
00744 
00745         for (bone = ebones->first; bone; bone = bone->next)
00746         {
00747                 float vec[3];
00748                 short pval[2];
00749                 int pdist;
00750 
00751                 if ((bone->flag & BONE_CONNECTED) == 0)
00752                 {
00753                         VECCOPY(vec, bone->head);
00754                         mul_m4_v3(ob->obmat, vec);
00755                         project_short_noclip(ar, vec, pval);
00756 
00757                         pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
00758 
00759                         if (pdist < *dist)
00760                         {
00761                                 *dist = pdist;
00762                                 pt = &boneSnap;
00763                                 VECCOPY(pt->p, vec);
00764                                 pt->type = PT_EXACT;
00765                         }
00766                 }
00767 
00768 
00769                 VECCOPY(vec, bone->tail);
00770                 mul_m4_v3(ob->obmat, vec);
00771                 project_short_noclip(ar, vec, pval);
00772 
00773                 pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]);
00774 
00775                 if (pdist < *dist)
00776                 {
00777                         *dist = pdist;
00778                         pt = &boneSnap;
00779                         VECCOPY(pt->p, vec);
00780                         pt->type = PT_EXACT;
00781                 }
00782         }
00783 
00784         return pt;
00785 }
00786 #endif
00787 
00788 void sk_resetOverdraw(SK_Sketch *sketch)
00789 {
00790         sketch->over.target = NULL;
00791         sketch->over.start = -1;
00792         sketch->over.end = -1;
00793         sketch->over.count = 0;
00794 }
00795 
00796 int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk)
00797 {
00798         return  sketch->over.target &&
00799                         sketch->over.count >= SK_OVERDRAW_LIMIT &&
00800                         (sketch->over.target == stk || stk == NULL) &&
00801                         (sketch->over.start != -1 || sketch->over.end != -1);
00802 }
00803 
00804 static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
00805 {
00806         if (sketch->over.target == NULL)
00807         {
00808                 SK_Stroke *target;
00809                 int closest_index = -1;
00810                 int dist = SNAP_MIN_DISTANCE * 2;
00811 
00812                 for (target = sketch->strokes.first; target; target = target->next)
00813                 {
00814                         if (target != stk)
00815                         {
00816                                 int index;
00817 
00818                                 SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1);
00819 
00820                                 if (spt != NULL)
00821                                 {
00822                                         sketch->over.target = target;
00823                                         closest_index = index;
00824                                 }
00825                         }
00826                 }
00827 
00828                 if (sketch->over.target != NULL)
00829                 {
00830                         if (closest_index > -1)
00831                         {
00832                                 if (sk_lastStrokePoint(stk)->type == PT_EXACT)
00833                                 {
00834                                         sketch->over.count = SK_OVERDRAW_LIMIT;
00835                                 }
00836                                 else
00837                                 {
00838                                         sketch->over.count++;
00839                                 }
00840                         }
00841 
00842                         if (stk->nb_points == 1)
00843                         {
00844                                 sketch->over.start = closest_index;
00845                         }
00846                         else
00847                         {
00848                                 sketch->over.end = closest_index;
00849                         }
00850                 }
00851         }
00852         else if (sketch->over.target != NULL)
00853         {
00854                 SK_Point *closest_pt = NULL;
00855                 int dist = SNAP_MIN_DISTANCE * 2;
00856                 int index;
00857 
00858                 closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1);
00859 
00860                 if (closest_pt != NULL)
00861                 {
00862                         if (sk_lastStrokePoint(stk)->type == PT_EXACT)
00863                         {
00864                                 sketch->over.count = SK_OVERDRAW_LIMIT;
00865                         }
00866                         else
00867                         {
00868                                 sketch->over.count++;
00869                         }
00870 
00871                         sketch->over.end = index;
00872                 }
00873                 else
00874                 {
00875                         sketch->over.end = -1;
00876                 }
00877         }
00878 }
00879 
00880 /* return 1 on reverse needed */
00881 static int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end)
00882 {
00883         int retval = 0;
00884 
00885         *start = sketch->over.start;
00886         *end = sketch->over.end;
00887 
00888         if (*start == -1)
00889         {
00890                 *start = 0;
00891         }
00892 
00893         if (*end == -1)
00894         {
00895                 *end = sketch->over.target->nb_points - 1;
00896         }
00897 
00898         if (*end < *start)
00899         {
00900                 int tmp = *start;
00901                 *start = *end;
00902                 *end = tmp;
00903                 retval = 1;
00904         }
00905 
00906         return retval;
00907 }
00908 
00909 static void sk_endOverdraw(SK_Sketch *sketch)
00910 {
00911         SK_Stroke *stk = sketch->active_stroke;
00912 
00913         if (sk_hasOverdraw(sketch, NULL))
00914         {
00915                 int start;
00916                 int end;
00917 
00918                 if (sk_adjustIndexes(sketch, &start, &end))
00919                 {
00920                         sk_reverseStroke(stk);
00921                 }
00922 
00923                 if (stk->nb_points > 1)
00924                 {
00925                         stk->points->type = sketch->over.target->points[start].type;
00926                         sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type;
00927                 }
00928 
00929                 sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end);
00930 
00931                 sk_removeStroke(sketch, stk);
00932 
00933                 sk_resetOverdraw(sketch);
00934         }
00935 }
00936 
00937 
00938 static void sk_startStroke(SK_Sketch *sketch)
00939 {
00940         SK_Stroke *stk = sk_createStroke();
00941 
00942         BLI_addtail(&sketch->strokes, stk);
00943         sketch->active_stroke = stk;
00944 
00945         sk_resetOverdraw(sketch);
00946 }
00947 
00948 static void sk_endStroke(bContext *C, SK_Sketch *sketch)
00949 {
00950         ToolSettings *ts = CTX_data_tool_settings(C);
00951         sk_shrinkStrokeBuffer(sketch->active_stroke);
00952 
00953         if (ts->bone_sketching & BONE_SKETCHING_ADJUST)
00954         {
00955                 sk_endOverdraw(sketch);
00956         }
00957 
00958         sketch->active_stroke = NULL;
00959 }
00960 
00961 static void sk_updateDrawData(SK_DrawData *dd)
00962 {
00963         dd->type = PT_CONTINUOUS;
00964 
00965         dd->previous_mval[0] = dd->mval[0];
00966         dd->previous_mval[1] = dd->mval[1];
00967 }
00968 
00969 static float sk_distanceDepth(bContext *C, float p1[3], float p2[3])
00970 {
00971         ARegion *ar = CTX_wm_region(C);
00972         RegionView3D *rv3d = ar->regiondata;
00973         float vec[3];
00974         float distance;
00975 
00976         sub_v3_v3v3(vec, p1, p2);
00977 
00978         project_v3_v3v3(vec, vec, rv3d->viewinv[2]);
00979 
00980         distance = len_v3(vec);
00981 
00982         if (dot_v3v3(rv3d->viewinv[2], vec) > 0)
00983         {
00984                 distance *= -1;
00985         }
00986 
00987         return distance;
00988 }
00989 
00990 static void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance)
00991 {
00992         ARegion *ar = CTX_wm_region(C);
00993         ScrArea *sa = CTX_wm_area(C);
00994         View3D *v3d = sa->spacedata.first;
00995 
00996         float progress = 0;
00997         int i;
00998 
00999         progress = len_v3v3(stk->points[start].p, stk->points[start - 1].p);
01000 
01001         for (i = start; i <= end; i++)
01002         {
01003                 float ray_start[3], ray_normal[3];
01004                 float delta = len_v3v3(stk->points[i].p, stk->points[i + 1].p);
01005                 float pval[2];
01006 
01007                 project_float(ar, stk->points[i].p, pval);
01008                 ED_view3d_win_to_ray(ar, v3d, pval, ray_start, ray_normal);
01009 
01010                 mul_v3_fl(ray_normal, distance * progress / length);
01011                 add_v3_v3(stk->points[i].p, ray_normal);
01012 
01013                 progress += delta ;
01014         }
01015 }
01016 
01017 static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd)
01018 {
01019         ARegion *ar = CTX_wm_region(C);
01020         /* copied from grease pencil, need fixing */
01021         SK_Point *last = sk_lastStrokePoint(stk);
01022         short cval[2];
01023         float fp[3] = {0, 0, 0};
01024         float dvec[3];
01025         float mval_f[2];
01026 
01027         if (last != NULL)
01028         {
01029                 VECCOPY(fp, last->p);
01030         }
01031 
01032         initgrabz(ar->regiondata, fp[0], fp[1], fp[2]);
01033 
01034         /* method taken from editview.c - mouse_cursor() */
01035         project_short_noclip(ar, fp, cval);
01036         VECSUB2D(mval_f, cval, dd->mval);
01037         ED_view3d_win_to_delta(ar, mval_f, dvec);
01038         sub_v3_v3v3(vec, fp, dvec);
01039 }
01040 
01041 static int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *UNUSED(sketch), SK_Stroke *stk, SK_DrawData *dd)
01042 {
01043         pt->type = dd->type;
01044         pt->mode = PT_PROJECT;
01045         sk_projectDrawPoint(C, pt->p, stk, dd);
01046 
01047         return 1;
01048 }
01049 
01050 static int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
01051 {
01052         ARegion *ar = CTX_wm_region(C);
01053         RegionView3D *rv3d = ar->regiondata;
01054         SK_Point pt;
01055 
01056         sk_initPoint(&pt, dd, rv3d->viewinv[2]);
01057 
01058         sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd);
01059 
01060         sk_appendStrokePoint(stk, &pt);
01061 
01062         return 1;
01063 }
01064 
01065 static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
01066 {
01067         ToolSettings *ts = CTX_data_tool_settings(C);
01068         int point_added = 0;
01069 
01070         if (ts->snap_mode == SCE_SNAP_MODE_VOLUME)
01071         {
01072                 DepthPeel *p1, *p2;
01073                 float *last_p = NULL;
01074                 float dist = FLT_MAX;
01075                 float p[3] = {0};
01076                 float size = 0;
01077                 float mvalf[2];
01078 
01079                 BLI_freelistN(&sketch->depth_peels);
01080                 sketch->depth_peels.first = sketch->depth_peels.last = NULL;
01081 
01082                 mvalf[0]= dd->mval[0];
01083                 mvalf[1]= dd->mval[1];
01084                 peelObjectsContext(C, &sketch->depth_peels, mvalf);
01085 
01086                 if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS)
01087                 {
01088                         last_p = stk->points[stk->nb_points - 1].p;
01089                 }
01090                 else if (LAST_SNAP_POINT_VALID)
01091                 {
01092                         last_p = LAST_SNAP_POINT;
01093                 }
01094 
01095 
01096                 for (p1 = sketch->depth_peels.first; p1; p1 = p1->next)
01097                 {
01098                         if (p1->flag == 0)
01099                         {
01100                                 float vec[3];
01101                                 float new_dist;
01102                                 float new_size = 0;
01103 
01104                                 p2 = NULL;
01105                                 p1->flag = 1;
01106 
01107                                 /* if peeling objects, take the first and last from each object */
01108                                 if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT)
01109                                 {
01110                                         DepthPeel *peel;
01111                                         for (peel = p1->next; peel; peel = peel->next)
01112                                         {
01113                                                 if (peel->ob == p1->ob)
01114                                                 {
01115                                                         peel->flag = 1;
01116                                                         p2 = peel;
01117                                                 }
01118                                         }
01119                                 }
01120                                 /* otherwise, pair first with second and so on */
01121                                 else
01122                                 {
01123                                         for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next)
01124                                         {
01125                                                 /* nothing to do here */
01126                                         }
01127                                 }
01128 
01129                                 if (p2)
01130                                 {
01131                                         p2->flag = 1;
01132 
01133                                         add_v3_v3v3(vec, p1->p, p2->p);
01134                                         mul_v3_fl(vec, 0.5f);
01135                                         new_size = len_v3v3(p1->p, p2->p);
01136                                 }
01137                                 else
01138                                 {
01139                                         VECCOPY(vec, p1->p);
01140                                 }
01141 
01142                                 if (last_p == NULL)
01143                                 {
01144                                         VECCOPY(p, vec);
01145                                         size = new_size;
01146                                         dist = 0;
01147                                         break;
01148                                 }
01149 
01150                                 new_dist = len_v3v3(last_p, vec);
01151 
01152                                 if (new_dist < dist)
01153                                 {
01154                                         VECCOPY(p, vec);
01155                                         dist = new_dist;
01156                                         size = new_size;
01157                                 }
01158                         }
01159                 }
01160 
01161                 if (dist != FLT_MAX)
01162                 {
01163                         pt->type = dd->type;
01164                         pt->mode = PT_SNAP;
01165                         pt->size = size / 2;
01166                         VECCOPY(pt->p, p);
01167 
01168                         point_added = 1;
01169                 }
01170 
01171                 //BLI_freelistN(&depth_peels);
01172         }
01173         else
01174         {
01175                 SK_Stroke *snap_stk;
01176                 float vec[3];
01177                 float no[3];
01178                 float mval[2];
01179                 int found = 0;
01180                 int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
01181 
01182                 /* snap to strokes */
01183                 // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */
01184                 for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next)
01185                 {
01186                         SK_Point *spt = NULL;
01187                         if (snap_stk == stk)
01188                         {
01189                                 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0);
01190                         }
01191                         else
01192                         {
01193                                 spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1);
01194                         }
01195 
01196                         if (spt != NULL)
01197                         {
01198                                 VECCOPY(pt->p, spt->p);
01199                                 point_added = 1;
01200                         }
01201                 }
01202                 
01203                 mval[0] = dd->mval[0];
01204                 mval[1] = dd->mval[1];
01205 
01206                 /* try to snap to closer object */
01207                 found = snapObjectsContext(C, mval, &dist, vec, no, SNAP_NOT_SELECTED);
01208                 if (found == 1)
01209                 {
01210                         pt->type = dd->type;
01211                         pt->mode = PT_SNAP;
01212                         VECCOPY(pt->p, vec);
01213 
01214                         point_added = 1;
01215                 }
01216         }
01217 
01218         return point_added;
01219 }
01220 
01221 static int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd)
01222 {
01223         int point_added;
01224         ARegion *ar = CTX_wm_region(C);
01225         RegionView3D *rv3d = ar->regiondata;
01226         SK_Point pt;
01227 
01228         sk_initPoint(&pt, dd, rv3d->viewinv[2]);
01229 
01230         point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd);
01231 
01232         if (point_added)
01233         {
01234                 float final_p[3];
01235                 float length, distance;
01236                 int total;
01237                 int i;
01238 
01239                 VECCOPY(final_p, pt.p);
01240 
01241                 sk_projectDrawPoint(C, pt.p, stk, dd);
01242                 sk_appendStrokePoint(stk, &pt);
01243 
01244                 /* update all previous point to give smooth Z progresion */
01245                 total = 0;
01246                 length = 0;
01247                 for (i = stk->nb_points - 2; i > 0; i--)
01248                 {
01249                         length += len_v3v3(stk->points[i].p, stk->points[i + 1].p);
01250                         total++;
01251                         if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT)
01252                         {
01253                                 break;
01254                         }
01255                 }
01256 
01257                 if (total > 1)
01258                 {
01259                         distance = sk_distanceDepth(C, final_p, stk->points[i].p);
01260 
01261                         sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance);
01262                 }
01263 
01264                 VECCOPY(stk->points[stk->nb_points - 1].p, final_p);
01265 
01266                 point_added = 1;
01267         }
01268 
01269         return point_added;
01270 }
01271 
01272 static void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
01273 {
01274         ToolSettings *ts = CTX_data_tool_settings(C);
01275         int point_added = 0;
01276 
01277         if (snap)
01278         {
01279                 point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd);
01280         }
01281 
01282         if (point_added == 0)
01283         {
01284                 point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd);
01285         }
01286 
01287         if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST)
01288         {
01289                 sk_updateOverdraw(C, sketch, stk, dd);
01290         }
01291 }
01292 
01293 static void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
01294 {
01295         int point_added = 0;
01296 
01297         if (snap)
01298         {
01299                 point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd);
01300                 LAST_SNAP_POINT_VALID = 1;
01301                 VECCOPY(LAST_SNAP_POINT, pt->p);
01302         }
01303         else
01304         {
01305                 LAST_SNAP_POINT_VALID = 0;
01306         }
01307 
01308         if (point_added == 0)
01309         {
01310                 point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd);
01311         }
01312 }
01313 
01314 /********************************************/
01315 
01316 static void* headPoint(void *arg);
01317 static void* tailPoint(void *arg);
01318 static void* nextPoint(void *arg);
01319 static void* nextNPoint(void *arg, int n);
01320 static void* peekPoint(void *arg, int n);
01321 static void* previousPoint(void *arg);
01322 static int   iteratorStopped(void *arg);
01323 
01324 static void initIteratorFct(SK_StrokeIterator *iter)
01325 {
01326         iter->head = headPoint;
01327         iter->tail = tailPoint;
01328         iter->peek = peekPoint;
01329         iter->next = nextPoint;
01330         iter->nextN = nextNPoint;
01331         iter->previous = previousPoint;
01332         iter->stopped = iteratorStopped;
01333 }
01334 
01335 static SK_Point* setIteratorValues(SK_StrokeIterator *iter, int index)
01336 {
01337         SK_Point *pt = NULL;
01338 
01339         if (index >= 0 && index < iter->length)
01340         {
01341                 pt = &(iter->stroke->points[iter->start + (iter->stride * index)]);
01342                 iter->p = pt->p;
01343                 iter->no = pt->no;
01344                 iter->size = pt->size;
01345         }
01346         else
01347         {
01348                 iter->p = NULL;
01349                 iter->no = NULL;
01350                 iter->size = 0;
01351         }
01352 
01353         return pt;
01354 }
01355 
01356 void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end)
01357 {
01358         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01359 
01360         initIteratorFct(iter);
01361         iter->stroke = stk;
01362 
01363         if (start < end)
01364         {
01365                 iter->start = start + 1;
01366                 iter->end = end - 1;
01367                 iter->stride = 1;
01368         }
01369         else
01370         {
01371                 iter->start = start - 1;
01372                 iter->end = end + 1;
01373                 iter->stride = -1;
01374         }
01375 
01376         iter->length = iter->stride * (iter->end - iter->start + 1);
01377 
01378         iter->index = -1;
01379 }
01380 
01381 
01382 static void* headPoint(void *arg)
01383 {
01384         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01385         SK_Point *result = NULL;
01386 
01387         result = &(iter->stroke->points[iter->start - iter->stride]);
01388         iter->p = result->p;
01389         iter->no = result->no;
01390         iter->size = result->size;
01391 
01392         return result;
01393 }
01394 
01395 static void* tailPoint(void *arg)
01396 {
01397         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01398         SK_Point *result = NULL;
01399 
01400         result = &(iter->stroke->points[iter->end + iter->stride]);
01401         iter->p = result->p;
01402         iter->no = result->no;
01403         iter->size = result->size;
01404 
01405         return result;
01406 }
01407 
01408 static void* nextPoint(void *arg)
01409 {
01410         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01411         SK_Point *result = NULL;
01412 
01413         iter->index++;
01414         if (iter->index < iter->length)
01415         {
01416                 result = setIteratorValues(iter, iter->index);
01417         }
01418 
01419         return result;
01420 }
01421 
01422 static void* nextNPoint(void *arg, int n)
01423 {
01424         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01425         SK_Point *result = NULL;
01426 
01427         iter->index += n;
01428 
01429         /* check if passed end */
01430         if (iter->index < iter->length)
01431         {
01432                 result = setIteratorValues(iter, iter->index);
01433         }
01434 
01435         return result;
01436 }
01437 
01438 static void* peekPoint(void *arg, int n)
01439 {
01440         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01441         SK_Point *result = NULL;
01442         int index = iter->index + n;
01443 
01444         /* check if passed end */
01445         if (index < iter->length)
01446         {
01447                 result = setIteratorValues(iter, index);
01448         }
01449 
01450         return result;
01451 }
01452 
01453 static void* previousPoint(void *arg)
01454 {
01455         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01456         SK_Point *result = NULL;
01457 
01458         if (iter->index > 0)
01459         {
01460                 iter->index--;
01461                 result = setIteratorValues(iter, iter->index);
01462         }
01463 
01464         return result;
01465 }
01466 
01467 static int iteratorStopped(void *arg)
01468 {
01469         SK_StrokeIterator *iter = (SK_StrokeIterator*)arg;
01470 
01471         if (iter->index >= iter->length)
01472         {
01473                 return 1;
01474         }
01475         else
01476         {
01477                 return 0;
01478         }
01479 }
01480 
01481 static void sk_convertStroke(bContext *C, SK_Stroke *stk)
01482 {
01483         Object *obedit = CTX_data_edit_object(C);
01484         ToolSettings *ts = CTX_data_tool_settings(C);
01485         bArmature *arm = obedit->data;
01486         SK_Point *head;
01487         EditBone *parent = NULL;
01488         float invmat[4][4]; /* move in caller function */
01489         float tmat[3][3];
01490         int head_index = 0;
01491         int i;
01492 
01493         head = NULL;
01494 
01495         invert_m4_m4(invmat, obedit->obmat);
01496 
01497         copy_m3_m4(tmat, obedit->obmat);
01498         transpose_m3(tmat);
01499 
01500         for (i = 0; i < stk->nb_points; i++)
01501         {
01502                 SK_Point *pt = stk->points + i;
01503 
01504                 if (pt->type == PT_EXACT)
01505                 {
01506                         if (head == NULL)
01507                         {
01508                                 head_index = i;
01509                                 head = pt;
01510                         }
01511                         else
01512                         {
01513                                 EditBone *bone = NULL;
01514                                 EditBone *new_parent;
01515 
01516                                 if (i - head_index > 1)
01517                                 {
01518                                         SK_StrokeIterator sk_iter;
01519                                         BArcIterator *iter = (BArcIterator*)&sk_iter;
01520 
01521                                         initStrokeIterator(iter, stk, head_index, i);
01522 
01523                                         if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE)
01524                                         {
01525                                                 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision);
01526                                         }
01527                                         else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH)
01528                                         {
01529                                                 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision);
01530                                         }
01531                                         else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED)
01532                                         {
01533                                                 bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision);
01534                                         }
01535                                 }
01536 
01537                                 if (bone == NULL)
01538                                 {
01539                                         bone = ED_armature_edit_bone_add(arm, "Bone");
01540 
01541                                         VECCOPY(bone->head, head->p);
01542                                         VECCOPY(bone->tail, pt->p);
01543 
01544                                         mul_m4_v3(invmat, bone->head);
01545                                         mul_m4_v3(invmat, bone->tail);
01546                                         setBoneRollFromNormal(bone, head->no, invmat, tmat);
01547                                 }
01548 
01549                                 new_parent = bone;
01550                                 bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
01551 
01552                                 /* move to end of chain */
01553                                 while (bone->parent != NULL)
01554                                 {
01555                                         bone = bone->parent;
01556                                         bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
01557                                 }
01558 
01559                                 if (parent != NULL)
01560                                 {
01561                                         bone->parent = parent;
01562                                         bone->flag |= BONE_CONNECTED;
01563                                 }
01564 
01565                                 parent = new_parent;
01566                                 head_index = i;
01567                                 head = pt;
01568                         }
01569                 }
01570         }
01571 }
01572 
01573 static void sk_convert(bContext *C, SK_Sketch *sketch)
01574 {
01575         ToolSettings *ts = CTX_data_tool_settings(C);
01576         SK_Stroke *stk;
01577 
01578         for (stk = sketch->strokes.first; stk; stk = stk->next)
01579         {
01580                 if (stk->selected == 1)
01581                 {
01582                         if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
01583                         {
01584                                 sk_retargetStroke(C, stk);
01585                         }
01586                         else
01587                         {
01588                                 sk_convertStroke(C, stk);
01589                         }
01590 //                      XXX
01591 //                      allqueue(REDRAWBUTSEDIT, 0);
01592                 }
01593         }
01594 }
01595 /******************* GESTURE *************************/
01596 
01597 
01598 /* returns the number of self intersections */
01599 static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture)
01600 {
01601         ARegion *ar = CTX_wm_region(C);
01602         int added = 0;
01603         int s_i;
01604 
01605         for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
01606         {
01607                 float s_p1[3] = {0, 0, 0};
01608                 float s_p2[3] = {0, 0, 0};
01609                 int g_i;
01610 
01611                 project_float(ar, gesture->points[s_i].p, s_p1);
01612                 project_float(ar, gesture->points[s_i + 1].p, s_p2);
01613 
01614                 /* start checking from second next, because two consecutive cannot intersect */
01615                 for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
01616                 {
01617                         float g_p1[3] = {0, 0, 0};
01618                         float g_p2[3] = {0, 0, 0};
01619                         float vi[3];
01620                         float lambda;
01621 
01622                         project_float(ar, gesture->points[g_i].p, g_p1);
01623                         project_float(ar, gesture->points[g_i + 1].p, g_p2);
01624 
01625                         if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
01626                         {
01627                                 SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
01628 
01629                                 isect->gesture_index = g_i;
01630                                 isect->before = s_i;
01631                                 isect->after = s_i + 1;
01632                                 isect->stroke = gesture;
01633 
01634                                 sub_v3_v3v3(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
01635                                 mul_v3_fl(isect->p, lambda);
01636                                 add_v3_v3(isect->p, gesture->points[s_i].p);
01637 
01638                                 BLI_addtail(list, isect);
01639 
01640                                 added++;
01641                         }
01642                 }
01643         }
01644 
01645         return added;
01646 }
01647 
01648 static int cmpIntersections(void *i1, void *i2)
01649 {
01650         SK_Intersection *isect1 = i1, *isect2 = i2;
01651 
01652         if (isect1->stroke == isect2->stroke)
01653         {
01654                 if (isect1->before < isect2->before)
01655                 {
01656                         return -1;
01657                 }
01658                 else if (isect1->before > isect2->before)
01659                 {
01660                         return 1;
01661                 }
01662                 else
01663                 {
01664                         if (isect1->lambda < isect2->lambda)
01665                         {
01666                                 return -1;
01667                         }
01668                         else if (isect1->lambda > isect2->lambda)
01669                         {
01670                                 return 1;
01671                         }
01672                 }
01673         }
01674 
01675         return 0;
01676 }
01677 
01678 
01679 /* returns the maximum number of intersections per stroke */
01680 static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
01681 {
01682         ARegion *ar = CTX_wm_region(C);
01683         ScrArea *sa = CTX_wm_area(C);
01684         View3D *v3d = sa->spacedata.first;
01685         SK_Stroke *stk;
01686         int added = 0;
01687 
01688         for (stk = sketch->strokes.first; stk; stk = stk->next)
01689         {
01690                 int s_added = 0;
01691                 int s_i;
01692 
01693                 for (s_i = 0; s_i < stk->nb_points - 1; s_i++)
01694                 {
01695                         float s_p1[3] = {0, 0, 0};
01696                         float s_p2[3] = {0, 0, 0};
01697                         int g_i;
01698 
01699                         project_float(ar, stk->points[s_i].p, s_p1);
01700                         project_float(ar, stk->points[s_i + 1].p, s_p2);
01701 
01702                         for (g_i = 0; g_i < gesture->nb_points - 1; g_i++)
01703                         {
01704                                 float g_p1[3] = {0, 0, 0};
01705                                 float g_p2[3] = {0, 0, 0};
01706                                 float vi[3];
01707                                 float lambda;
01708 
01709                                 project_float(ar, gesture->points[g_i].p, g_p1);
01710                                 project_float(ar, gesture->points[g_i + 1].p, g_p2);
01711 
01712                                 if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
01713                                 {
01714                                         SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
01715                                         float ray_start[3], ray_end[3];
01716                                         float mval[2];
01717 
01718                                         isect->gesture_index = g_i;
01719                                         isect->before = s_i;
01720                                         isect->after = s_i + 1;
01721                                         isect->stroke = stk;
01722                                         isect->lambda = lambda;
01723 
01724                                         mval[0] = vi[0];
01725                                         mval[1] = vi[1];
01726                                         ED_view3d_win_to_segment_clip(ar, v3d, mval, ray_start, ray_end);
01727 
01728                                         isect_line_line_v3(     stk->points[s_i].p,
01729                                                                                 stk->points[s_i + 1].p,
01730                                                                                 ray_start,
01731                                                                                 ray_end,
01732                                                                                 isect->p,
01733                                                                                 vi);
01734 
01735                                         BLI_addtail(list, isect);
01736 
01737                                         s_added++;
01738                                 }
01739                         }
01740                 }
01741 
01742                 added = MAX2(s_added, added);
01743         }
01744 
01745         BLI_sortlist(list, cmpIntersections);
01746 
01747         return added;
01748 }
01749 
01750 static int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture)
01751 {
01752         SK_StrokeIterator sk_iter;
01753         BArcIterator *iter = (BArcIterator*)&sk_iter;
01754 
01755         float CORRELATION_THRESHOLD = 0.99f;
01756         float *vec;
01757         int i, j;
01758 
01759         sk_appendStrokePoint(segments, &gesture->points[0]);
01760         vec = segments->points[segments->nb_points - 1].p;
01761 
01762         initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1);
01763 
01764         for (i = 1, j = 0; i < gesture->nb_points; i++)
01765         {
01766                 float n[3];
01767 
01768                 /* Calculate normal */
01769                 sub_v3_v3v3(n, gesture->points[i].p, vec);
01770 
01771                 if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD)
01772                 {
01773                         j = i - 1;
01774                         sk_appendStrokePoint(segments, &gesture->points[j]);
01775                         vec = segments->points[segments->nb_points - 1].p;
01776                         segments->points[segments->nb_points - 1].type = PT_EXACT;
01777                 }
01778         }
01779 
01780         sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]);
01781 
01782         return segments->nb_points - 1;
01783 }
01784 
01785 int sk_detectCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01786 {
01787         if (gest->nb_segments == 1 && gest->nb_intersections == 1)
01788         {
01789                 return 1;
01790         }
01791 
01792         return 0;
01793 }
01794 
01795 void sk_applyCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01796 {
01797         SK_Intersection *isect;
01798 
01799         for (isect = gest->intersections.first; isect; isect = isect->next)
01800         {
01801                 SK_Point pt;
01802 
01803                 pt.type = PT_EXACT;
01804                 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
01805                 VECCOPY(pt.p, isect->p);
01806                 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
01807 
01808                 sk_insertStrokePoint(isect->stroke, &pt, isect->after);
01809         }
01810 }
01811 
01812 int sk_detectTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01813 {
01814         if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0)
01815         {
01816                 float s1[3], s2[3];
01817                 float angle;
01818 
01819                 sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p);
01820                 sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p);
01821 
01822                 angle = RAD2DEG(angle_v2v2(s1, s2));
01823 
01824                 if (angle > 60 && angle < 120)
01825                 {
01826                         return 1;
01827                 }
01828         }
01829 
01830         return 0;
01831 }
01832 
01833 void sk_applyTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01834 {
01835         SK_Intersection *isect;
01836         float trim_dir[3];
01837 
01838         sub_v3_v3v3(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p);
01839 
01840         for (isect = gest->intersections.first; isect; isect = isect->next)
01841         {
01842                 SK_Point pt;
01843                 float stroke_dir[3];
01844 
01845                 pt.type = PT_EXACT;
01846                 pt.mode = PT_PROJECT; /* take mode from neighbouring points */
01847                 VECCOPY(pt.p, isect->p);
01848                 VECCOPY(pt.no, isect->stroke->points[isect->before].no);
01849 
01850                 sub_v3_v3v3(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p);
01851 
01852                 /* same direction, trim end */
01853                 if (dot_v3v3(stroke_dir, trim_dir) > 0)
01854                 {
01855                         sk_replaceStrokePoint(isect->stroke, &pt, isect->after);
01856                         sk_trimStroke(isect->stroke, 0, isect->after);
01857                 }
01858                 /* else, trim start */
01859                 else
01860                 {
01861                         sk_replaceStrokePoint(isect->stroke, &pt, isect->before);
01862                         sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1);
01863                 }
01864 
01865         }
01866 }
01867 
01868 int sk_detectCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01869 {
01870         if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1)
01871         {
01872                 SK_Intersection *isect, *self_isect;
01873 
01874                 /* get the the last intersection of the first pair */
01875                 for( isect = gest->intersections.first; isect; isect = isect->next )
01876                 {
01877                         if (isect->stroke == isect->next->stroke)
01878                         {
01879                                 isect = isect->next;
01880                                 break;
01881                         }
01882                 }
01883 
01884                 self_isect = gest->self_intersections.first;
01885 
01886                 if (isect && isect->gesture_index < self_isect->gesture_index)
01887                 {
01888                         return 1;
01889                 }
01890         }
01891 
01892         return 0;
01893 }
01894 
01895 void sk_applyCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01896 {
01897         SK_Intersection *isect;
01898         int command = 1;
01899 
01900 //      XXX
01901 //      command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3");
01902         if(command < 1) return;
01903 
01904         for (isect = gest->intersections.first; isect; isect = isect->next)
01905         {
01906                 SK_Intersection *i2;
01907 
01908                 i2 = isect->next;
01909 
01910                 if (i2 && i2->stroke == isect->stroke)
01911                 {
01912                         switch (command)
01913                         {
01914                                 case 1:
01915                                         sk_flattenStroke(isect->stroke, isect->before, i2->after);
01916                                         break;
01917                                 case 2:
01918                                         sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p);
01919                                         break;
01920                                 case 3:
01921                                         sk_polygonizeStroke(isect->stroke, isect->before, i2->after);
01922                                         break;
01923                         }
01924 
01925                         isect = i2;
01926                 }
01927         }
01928 }
01929 
01930 int sk_detectDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01931 {
01932         if (gest->nb_segments == 2 && gest->nb_intersections == 2)
01933         {
01934                 float s1[3], s2[3];
01935                 float angle;
01936 
01937                 sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p);
01938                 sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p);
01939 
01940                 angle = RAD2DEG(angle_v2v2(s1, s2));
01941 
01942                 if (angle > 120)
01943                 {
01944                         return 1;
01945                 }
01946         }
01947 
01948         return 0;
01949 }
01950 
01951 void sk_applyDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *sketch)
01952 {
01953         SK_Intersection *isect;
01954 
01955         for (isect = gest->intersections.first; isect; isect = isect->next)
01956         {
01957                 /* only delete strokes that are crossed twice */
01958                 if (isect->next && isect->next->stroke == isect->stroke)
01959                 {
01960                         isect = isect->next;
01961 
01962                         sk_removeStroke(sketch, isect->stroke);
01963                 }
01964         }
01965 }
01966 
01967 int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
01968 {
01969         ARegion *ar = CTX_wm_region(C);
01970         if (gest->nb_segments > 2 && gest->nb_intersections == 2)
01971         {
01972                 short start_val[2], end_val[2];
01973                 short dist;
01974 
01975                 project_short_noclip(ar, gest->stk->points[0].p, start_val);
01976                 project_short_noclip(ar, sk_lastStrokePoint(gest->stk)->p, end_val);
01977 
01978                 dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
01979 
01980                 /* if gesture is a circle */
01981                 if ( dist <= 20 )
01982                 {
01983                         SK_Intersection *isect;
01984 
01985                         /* check if it circled around an exact point */
01986                         for (isect = gest->intersections.first; isect; isect = isect->next)
01987                         {
01988                                 /* only delete strokes that are crossed twice */
01989                                 if (isect->next && isect->next->stroke == isect->stroke)
01990                                 {
01991                                         int start_index, end_index;
01992                                         int i;
01993 
01994                                         start_index = MIN2(isect->after, isect->next->after);
01995                                         end_index = MAX2(isect->before, isect->next->before);
01996 
01997                                         for (i = start_index; i <= end_index; i++)
01998                                         {
01999                                                 if (isect->stroke->points[i].type == PT_EXACT)
02000                                                 {
02001                                                         return 1; /* at least one exact point found, stop detect here */
02002                                                 }
02003                                         }
02004 
02005                                         /* skip next */
02006                                         isect = isect->next;
02007                                 }
02008                         }
02009                 }
02010         }
02011 
02012         return 0;
02013 }
02014 
02015 void sk_applyMergeGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
02016 {
02017         SK_Intersection *isect;
02018 
02019         /* check if it circled around an exact point */
02020         for (isect = gest->intersections.first; isect; isect = isect->next)
02021         {
02022                 /* only merge strokes that are crossed twice */
02023                 if (isect->next && isect->next->stroke == isect->stroke)
02024                 {
02025                         int start_index, end_index;
02026                         int i;
02027 
02028                         start_index = MIN2(isect->after, isect->next->after);
02029                         end_index = MAX2(isect->before, isect->next->before);
02030 
02031                         for (i = start_index; i <= end_index; i++)
02032                         {
02033                                 /* if exact, switch to continuous */
02034                                 if (isect->stroke->points[i].type == PT_EXACT)
02035                                 {
02036                                         isect->stroke->points[i].type = PT_CONTINUOUS;
02037                                 }
02038                         }
02039 
02040                         /* skip next */
02041                         isect = isect->next;
02042                 }
02043         }
02044 }
02045 
02046 int sk_detectReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
02047 {
02048         if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0)
02049         {
02050                 SK_Intersection *isect;
02051 
02052                 /* check if it circled around an exact point */
02053                 for (isect = gest->intersections.first; isect; isect = isect->next)
02054                 {
02055                         /* only delete strokes that are crossed twice */
02056                         if (isect->next && isect->next->stroke == isect->stroke)
02057                         {
02058                                 float start_v[3], end_v[3];
02059                                 float angle;
02060 
02061                                 if (isect->gesture_index < isect->next->gesture_index)
02062                                 {
02063                                         sub_v3_v3v3(start_v, isect->p, gest->stk->points[0].p);
02064                                         sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p);
02065                                 }
02066                                 else
02067                                 {
02068                                         sub_v3_v3v3(start_v, isect->next->p, gest->stk->points[0].p);
02069                                         sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p);
02070                                 }
02071 
02072                                 angle = RAD2DEG(angle_v2v2(start_v, end_v));
02073 
02074                                 if (angle > 120)
02075                                 {
02076                                         return 1;
02077                                 }
02078 
02079                                 /* skip next */
02080                                 isect = isect->next;
02081                         }
02082                 }
02083         }
02084 
02085         return 0;
02086 }
02087 
02088 void sk_applyReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
02089 {
02090         SK_Intersection *isect;
02091 
02092         for (isect = gest->intersections.first; isect; isect = isect->next)
02093         {
02094                 /* only reverse strokes that are crossed twice */
02095                 if (isect->next && isect->next->stroke == isect->stroke)
02096                 {
02097                         sk_reverseStroke(isect->stroke);
02098 
02099                         /* skip next */
02100                         isect = isect->next;
02101                 }
02102         }
02103 }
02104 
02105 int sk_detectConvertGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch))
02106 {
02107         if (gest->nb_segments == 3 && gest->nb_self_intersections == 1)
02108         {
02109                 return 1;
02110         }
02111         return 0;
02112 }
02113 
02114 void sk_applyConvertGesture(bContext *C, SK_Gesture *UNUSED(gest), SK_Sketch *sketch)
02115 {
02116         sk_convert(C, sketch);
02117 }
02118 
02119 static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch)
02120 {
02121         gest->intersections.first = gest->intersections.last = NULL;
02122         gest->self_intersections.first = gest->self_intersections.last = NULL;
02123 
02124         gest->segments = sk_createStroke();
02125         gest->stk = sketch->gesture;
02126 
02127         gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk);
02128         gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk);
02129         gest->nb_segments = sk_getSegments(gest->segments, gest->stk);
02130 }
02131 
02132 static void sk_freeGesture(SK_Gesture *gest)
02133 {
02134         sk_freeStroke(gest->segments);
02135         BLI_freelistN(&gest->intersections);
02136         BLI_freelistN(&gest->self_intersections);
02137 }
02138 
02139 static void sk_applyGesture(bContext *C, SK_Sketch *sketch)
02140 {
02141         SK_Gesture gest;
02142         SK_GestureAction *act;
02143 
02144         sk_initGesture(C, &gest, sketch);
02145 
02146         /* detect and apply */
02147         for (act = GESTURE_ACTIONS; act->apply != NULL; act++)
02148         {
02149                 if (act->detect(C, &gest, sketch))
02150                 {
02151                         act->apply(C, &gest, sketch);
02152                         break;
02153                 }
02154         }
02155 
02156         sk_freeGesture(&gest);
02157 }
02158 
02159 /********************************************/
02160 
02161 
02162 static int sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], int extend)
02163 {
02164         ViewContext vc;
02165         rcti rect;
02166         unsigned int buffer[MAXPICKBUF];
02167         short hits;
02168 
02169         view3d_set_viewcontext(C, &vc);
02170 
02171         rect.xmin= mval[0]-5;
02172         rect.xmax= mval[0]+5;
02173         rect.ymin= mval[1]-5;
02174         rect.ymax= mval[1]+5;
02175 
02176         hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
02177 
02178         if (hits>0)
02179         {
02180                 int besthitresult = -1;
02181 
02182                 if(hits == 1) {
02183                         besthitresult = buffer[3];
02184                 }
02185                 else {
02186                         besthitresult = buffer[3];
02187                         /* loop and get best hit */
02188                 }
02189 
02190                 if (besthitresult > 0)
02191                 {
02192                         SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1);
02193 
02194                         if (extend == 0)
02195                         {
02196                                 sk_selectAllSketch(sketch, -1);
02197 
02198                                 selected_stk->selected = 1;
02199                         }
02200                         else
02201                         {
02202                                 selected_stk->selected ^= 1;
02203                         }
02204 
02205 
02206                 }
02207                 return 1;
02208         }
02209 
02210         return 0;
02211 }
02212 
02213 #if 0 /* UNUSED 2.5 */
02214 static void sk_queueRedrawSketch(SK_Sketch *sketch)
02215 {
02216         if (sketch->active_stroke != NULL)
02217         {
02218                 SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
02219 
02220                 if (last != NULL)
02221                 {
02222 //                      XXX
02223 //                      allqueue(REDRAWVIEW3D, 0);
02224                 }
02225         }
02226 }
02227 #endif
02228 
02229 static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, int with_names)
02230 {
02231         ToolSettings *ts= scene->toolsettings;
02232         SK_Stroke *stk;
02233 
02234         glClear(GL_DEPTH_BUFFER_BIT);
02235         glEnable(GL_DEPTH_TEST);
02236 
02237         if (with_names)
02238         {
02239                 int id;
02240                 for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next)
02241                 {
02242                         sk_drawStroke(stk, id, NULL, -1, -1);
02243                 }
02244 
02245                 glLoadName(-1);
02246         }
02247         else
02248         {
02249                 float selected_rgb[3] = {1, 0, 0};
02250                 float unselected_rgb[3] = {1, 0.5, 0};
02251 
02252                 for (stk = sketch->strokes.first; stk; stk = stk->next)
02253                 {
02254                         int start = -1;
02255                         int end = -1;
02256 
02257                         if (sk_hasOverdraw(sketch, stk))
02258                         {
02259                                 sk_adjustIndexes(sketch, &start, &end);
02260                         }
02261 
02262                         sk_drawStroke(stk, -1, (stk->selected==1?selected_rgb:unselected_rgb), start, end);
02263 
02264                         if (stk->selected == 1)
02265                         {
02266                                 sk_drawStrokeSubdivision(ts, stk);
02267                         }
02268                 }
02269 
02270                 if (sketch->active_stroke != NULL)
02271                 {
02272                         SK_Point *last = sk_lastStrokePoint(sketch->active_stroke);
02273 
02274                         if (ts->bone_sketching & BONE_SKETCHING_QUICK)
02275                         {
02276                                 sk_drawStrokeSubdivision(ts, sketch->active_stroke);
02277                         }
02278 
02279                         if (last != NULL)
02280                         {
02281                                 GLUquadric *quad = gluNewQuadric();
02282                                 gluQuadricNormals(quad, GLU_SMOOTH);
02283 
02284                                 glPushMatrix();
02285 
02286                                 glEnable(GL_BLEND);
02287                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
02288 
02289                                 switch (sketch->next_point.mode)
02290                                 {
02291                                         case PT_SNAP:
02292                                                 glColor3f(0, 1, 0);
02293                                                 break;
02294                                         case PT_PROJECT:
02295                                                 glColor3f(0, 0, 0);
02296                                                 break;
02297                                 }
02298 
02299                                 sk_drawPoint(quad, &sketch->next_point, 0.1);
02300 
02301                                 glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
02302 
02303                                 sk_drawEdge(quad, last, &sketch->next_point, 0.1);
02304 
02305                                 glDisable(GL_BLEND);
02306 
02307                                 glPopMatrix();
02308 
02309                                 gluDeleteQuadric(quad);
02310                         }
02311                 }
02312         }
02313 
02314 #if 0
02315         if (sketch->depth_peels.first != NULL)
02316         {
02317                 float colors[8][3] = {
02318                                                                 {1, 0, 0},
02319                                                                 {0, 1, 0},
02320                                                                 {0, 0, 1},
02321                                                                 {1, 1, 0},
02322                                                                 {1, 0, 1},
02323                                                                 {0, 1, 1},
02324                                                                 {1, 1, 1},
02325                                                                 {0, 0, 0}
02326                                                         };
02327                 DepthPeel *p;
02328                 GLUquadric *quad = gluNewQuadric();
02329                 gluQuadricNormals(quad, GLU_SMOOTH);
02330 
02331                 for (p = sketch->depth_peels.first; p; p = p->next)
02332                 {
02333                         int index = GET_INT_FROM_POINTER(p->ob);
02334                         index = (index >> 5) & 7;
02335 
02336                         glColor3fv(colors[index]);
02337                         glPushMatrix();
02338                         glTranslatef(p->p[0], p->p[1], p->p[2]);
02339                         gluSphere(quad, 0.02, 8, 8);
02340                         glPopMatrix();
02341                 }
02342 
02343                 gluDeleteQuadric(quad);
02344         }
02345 #endif
02346 
02347         glDisable(GL_DEPTH_TEST);
02348 
02349         /* only draw gesture in active area */
02350         if (sketch->gesture != NULL /*&& area_is_active_area(G.vd->area)*/)
02351         {
02352                 float gesture_rgb[3] = {0, 0.5, 1};
02353                 sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
02354         }
02355 }
02356 
02357 static int sk_finish_stroke(bContext *C, SK_Sketch *sketch)
02358 {
02359         ToolSettings *ts = CTX_data_tool_settings(C);
02360 
02361         if (sketch->active_stroke != NULL)
02362         {
02363                 SK_Stroke *stk = sketch->active_stroke;
02364 
02365                 sk_endStroke(C, sketch);
02366 
02367                 if (ts->bone_sketching & BONE_SKETCHING_QUICK)
02368                 {
02369                         if (ts->bone_sketching_convert == SK_CONVERT_RETARGET)
02370                         {
02371                                 sk_retargetStroke(C, stk);
02372                         }
02373                         else
02374                         {
02375                                 sk_convertStroke(C, stk);
02376                         }
02377 //                      XXX
02378 //                      BIF_undo_push("Convert Sketch");
02379                         sk_removeStroke(sketch, stk);
02380 //                      XXX
02381 //                      allqueue(REDRAWBUTSEDIT, 0);
02382                 }
02383 
02384 //              XXX
02385 //              allqueue(REDRAWVIEW3D, 0);
02386                 return 1;
02387         }
02388 
02389         return 0;
02390 }
02391 
02392 static void sk_start_draw_stroke(SK_Sketch *sketch)
02393 {
02394         if (sketch->active_stroke == NULL)
02395         {
02396                 sk_startStroke(sketch);
02397                 sk_selectAllSketch(sketch, -1);
02398 
02399                 sketch->active_stroke->selected = 1;
02400         }
02401 }
02402 
02403 static void sk_start_draw_gesture(SK_Sketch *sketch)
02404 {
02405         sketch->gesture = sk_createStroke();
02406 }
02407 
02408 static int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, short snap)
02409 {
02410         if (sk_stroke_filtermval(dd))
02411         {
02412                 sk_addStrokePoint(C, sketch, stk, dd, snap);
02413                 sk_updateDrawData(dd);
02414                 sk_updateNextPoint(sketch, stk);
02415                 
02416                 return 1;
02417         }
02418 
02419         return 0;
02420 }
02421 
02422 static int ValidSketchViewContext(ViewContext *vc)
02423 {
02424         Object *obedit = vc->obedit;
02425         Scene *scene= vc->scene;
02426 
02427         if (obedit &&
02428                 obedit->type == OB_ARMATURE &&
02429                 scene->toolsettings->bone_sketching & BONE_SKETCHING)
02430         {
02431                 return 1;
02432         }
02433         else
02434         {
02435                 return 0;
02436         }
02437 }
02438 
02439 int BDR_drawSketchNames(ViewContext *vc)
02440 {
02441         if (ValidSketchViewContext(vc))
02442         {
02443                 SK_Sketch *sketch = viewcontextSketch(vc, 0);
02444                 if (sketch)
02445                 {
02446                         sk_drawSketch(vc->scene, vc->v3d, sketch, 1);
02447                         return 1;
02448                 }
02449         }
02450 
02451         return 0;
02452 }
02453 
02454 void BDR_drawSketch(const bContext *C)
02455 {
02456         if (ED_operator_sketch_mode(C))
02457         {
02458                 SK_Sketch *sketch = contextSketch(C, 0);
02459                 if (sketch)
02460                 {
02461                         sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), sketch, 0);
02462                 }
02463         }
02464 }
02465 
02466 static int sketch_delete(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
02467 {
02468         SK_Sketch *sketch = contextSketch(C, 0);
02469         if (sketch)
02470         {
02471                 sk_deleteSelectedStrokes(sketch);
02472 //                      allqueue(REDRAWVIEW3D, 0);
02473         }
02474         WM_event_add_notifier(C, NC_SCREEN|ND_SKETCH|NA_REMOVED, NULL);
02475         return OPERATOR_FINISHED;
02476 }
02477 
02478 void BIF_sk_selectStroke(bContext *C, const int mval[2], short extend)
02479 {
02480         ToolSettings *ts = CTX_data_tool_settings(C);
02481         SK_Sketch *sketch = contextSketch(C, 0);
02482 
02483         if (sketch != NULL && ts->bone_sketching & BONE_SKETCHING)
02484         {
02485                 if (sk_selectStroke(C, sketch, mval, extend))
02486                         ED_area_tag_redraw(CTX_wm_area(C));
02487         }
02488 }
02489 
02490 void BIF_convertSketch(bContext *C)
02491 {
02492         if (ED_operator_sketch_full_mode(C))
02493         {
02494                 SK_Sketch *sketch = contextSketch(C, 0);
02495                 if (sketch)
02496                 {
02497                         sk_convert(C, sketch);
02498 //                      BIF_undo_push("Convert Sketch");
02499 //                      allqueue(REDRAWVIEW3D, 0);
02500 //                      allqueue(REDRAWBUTSEDIT, 0);
02501                 }
02502         }
02503 }
02504 
02505 void BIF_deleteSketch(bContext *C)
02506 {
02507         if (ED_operator_sketch_full_mode(C))
02508         {
02509                 SK_Sketch *sketch = contextSketch(C, 0);
02510                 if (sketch)
02511                 {
02512                         sk_deleteSelectedStrokes(sketch);
02513 //                      BIF_undo_push("Convert Sketch");
02514 //                      allqueue(REDRAWVIEW3D, 0);
02515                 }
02516         }
02517 }
02518 
02519 #if 0
02520 void BIF_selectAllSketch(bContext *C, int mode)
02521 {
02522         if (BIF_validSketchMode(C))
02523         {
02524                 SK_Sketch *sketch = contextSketch(C, 0);
02525                 if (sketch)
02526                 {
02527                         sk_selectAllSketch(sketch, mode);
02528 //                      XXX
02529 //                      allqueue(REDRAWVIEW3D, 0);
02530                 }
02531         }
02532 }
02533 #endif
02534 
02535 SK_Sketch* contextSketch(const bContext *C, int create)
02536 {
02537         Object *obedit = CTX_data_edit_object(C);
02538         SK_Sketch *sketch = NULL;
02539 
02540         if (obedit && obedit->type == OB_ARMATURE)
02541         {
02542                 bArmature *arm = obedit->data;
02543         
02544                 if (arm->sketch == NULL && create)
02545                 {
02546                         arm->sketch = createSketch();
02547                 }
02548                 sketch = arm->sketch;
02549         }
02550 
02551         return sketch;
02552 }
02553 
02554 SK_Sketch* viewcontextSketch(ViewContext *vc, int create)
02555 {
02556         Object *obedit = vc->obedit;
02557         SK_Sketch *sketch = NULL;
02558 
02559         if (obedit && obedit->type == OB_ARMATURE)
02560         {
02561                 bArmature *arm = obedit->data;
02562         
02563                 if (arm->sketch == NULL && create)
02564                 {
02565                         arm->sketch = createSketch();
02566                 }
02567                 sketch = arm->sketch;
02568         }
02569 
02570         return sketch;
02571 }
02572 
02573 static int sketch_convert(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
02574 {
02575         SK_Sketch *sketch = contextSketch(C, 0);
02576         if (sketch != NULL)
02577         {
02578                 sk_convert(C, sketch);
02579                 ED_area_tag_redraw(CTX_wm_area(C));
02580         }
02581         return OPERATOR_FINISHED;
02582 }
02583 
02584 static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
02585 {
02586         SK_Sketch *sketch = contextSketch(C, 0);
02587         if (sketch != NULL)
02588         {
02589                 sk_cancelStroke(sketch);
02590                 ED_area_tag_redraw(CTX_wm_area(C));
02591                 return OPERATOR_FINISHED;
02592         }
02593         return OPERATOR_PASS_THROUGH;
02594 }
02595 
02596 static int sketch_finish(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
02597 {
02598         SK_Sketch *sketch = contextSketch(C, 0);
02599         if (sketch != NULL)
02600         {
02601                 if (sk_finish_stroke(C, sketch))
02602                 {
02603                         ED_area_tag_redraw(CTX_wm_area(C));
02604                         return OPERATOR_FINISHED;
02605                 }
02606         }
02607         return OPERATOR_PASS_THROUGH;
02608 }
02609 
02610 static int sketch_select(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
02611 {
02612         SK_Sketch *sketch = contextSketch(C, 0);
02613         if (sketch)
02614         {
02615                 short extend = 0;
02616                 if (sk_selectStroke(C, sketch, event->mval, extend))
02617                         ED_area_tag_redraw(CTX_wm_area(C));
02618         }
02619 
02620         return OPERATOR_FINISHED;
02621 }
02622 
02623 static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op)
02624 {
02625         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
02626         sk_cancelStroke(sketch);
02627         MEM_freeN(op->customdata);
02628         return OPERATOR_CANCELLED;
02629 }
02630 
02631 static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event)
02632 {
02633         short snap = RNA_boolean_get(op->ptr, "snap");
02634         SK_DrawData *dd;
02635         SK_Sketch *sketch = contextSketch(C, 1);
02636 
02637         op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
02638         sk_initDrawData(dd, event->mval);
02639 
02640         sk_start_draw_stroke(sketch);
02641 
02642         sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap);
02643 
02644         WM_event_add_modal_handler(C, op);
02645 
02646         return OPERATOR_RUNNING_MODAL;
02647 }
02648 
02649 static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op)
02650 {
02651         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
02652         sk_cancelStroke(sketch);
02653         MEM_freeN(op->customdata);
02654         return OPERATOR_CANCELLED;
02655 }
02656 
02657 static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event)
02658 {
02659         short snap = RNA_boolean_get(op->ptr, "snap");
02660         SK_DrawData *dd;
02661         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
02662         sk_cancelStroke(sketch);
02663 
02664         op->customdata = dd = MEM_callocN(sizeof("SK_DrawData"), "SketchDrawData");
02665         sk_initDrawData(dd, event->mval);
02666 
02667         sk_start_draw_gesture(sketch);
02668         sk_draw_stroke(C, sketch, sketch->gesture, dd, snap);
02669 
02670         WM_event_add_modal_handler(C, op);
02671 
02672         return OPERATOR_RUNNING_MODAL;
02673 }
02674 
02675 static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short gesture, SK_Stroke *stk)
02676 {
02677         short snap = RNA_boolean_get(op->ptr, "snap");
02678         SK_DrawData *dd = op->customdata;
02679         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
02680         int retval = OPERATOR_RUNNING_MODAL;
02681 
02682         switch (event->type)
02683         {
02684         case LEFTCTRLKEY:
02685         case RIGHTCTRLKEY:
02686                 snap = event->ctrl;
02687                 RNA_boolean_set(op->ptr, "snap", snap);
02688                 break;
02689         case MOUSEMOVE:
02690         case INBETWEEN_MOUSEMOVE:
02691                 dd->mval[0] = event->mval[0];
02692                 dd->mval[1] = event->mval[1];
02693                 sk_draw_stroke(C, sketch, stk, dd, snap);
02694                 ED_area_tag_redraw(CTX_wm_area(C));
02695                 break;
02696         case ESCKEY:
02697                 op->type->cancel(C, op);
02698                 ED_area_tag_redraw(CTX_wm_area(C));
02699                 retval = OPERATOR_CANCELLED;
02700                 break;
02701         case LEFTMOUSE:
02702                 if (event->val == KM_RELEASE)
02703                 {
02704                         if (gesture == 0)
02705                         {
02706                                 sk_endContinuousStroke(stk);
02707                                 sk_filterLastContinuousStroke(stk);
02708                                 sk_updateNextPoint(sketch, stk);
02709                                 ED_area_tag_redraw(CTX_wm_area(C));
02710                                 MEM_freeN(op->customdata);
02711                                 retval = OPERATOR_FINISHED;
02712                         }
02713                         else
02714                         {
02715                                 sk_endContinuousStroke(stk);
02716                                 sk_filterLastContinuousStroke(stk);
02717 
02718                                 if (stk->nb_points > 1)
02719                                 {
02720                                         /* apply gesture here */
02721                                         sk_applyGesture(C, sketch);
02722                                 }
02723 
02724                                 sk_freeStroke(stk);
02725                                 sketch->gesture = NULL;
02726 
02727                                 ED_area_tag_redraw(CTX_wm_area(C));
02728                                 MEM_freeN(op->customdata);
02729                                 retval = OPERATOR_FINISHED;
02730                         }
02731                 }
02732                 break;
02733         }
02734 
02735         return retval;
02736 }
02737 
02738 static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event)
02739 {
02740         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
02741         return sketch_draw_modal(C, op, event, 0, sketch->active_stroke);
02742 }
02743 
02744 static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event)
02745 {
02746         SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */
02747         return sketch_draw_modal(C, op, event, 1, sketch->gesture);
02748 }
02749 
02750 static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event)
02751 {
02752         short snap = RNA_boolean_get(op->ptr, "snap");
02753         SK_Sketch *sketch = contextSketch(C, 0);
02754 
02755         if (sketch)
02756         {
02757                 SK_DrawData dd;
02758 
02759                 sk_initDrawData(&dd, event->mval);
02760                 sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, snap);
02761                 ED_area_tag_redraw(CTX_wm_area(C));
02762         }
02763 
02764         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
02765 }
02766 
02767 /* ============================================== Poll Functions ============================================= */
02768 
02769 int ED_operator_sketch_mode_active_stroke(bContext *C)
02770 {
02771         ToolSettings *ts = CTX_data_tool_settings(C);
02772         SK_Sketch *sketch = contextSketch(C, 0);
02773 
02774         if (ts->bone_sketching & BONE_SKETCHING &&
02775                 sketch != NULL &&
02776                 sketch->active_stroke != NULL)
02777         {
02778                 return 1;
02779         }
02780         else
02781         {
02782                 return 0;
02783         }
02784 }
02785 
02786 static int ED_operator_sketch_mode_gesture(bContext *C)
02787 {
02788         ToolSettings *ts = CTX_data_tool_settings(C);
02789         SK_Sketch *sketch = contextSketch(C, 0);
02790 
02791         if (ts->bone_sketching & BONE_SKETCHING &&
02792                 (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 &&
02793                 sketch != NULL &&
02794                 sketch->active_stroke == NULL)
02795         {
02796                 return 1;
02797         }
02798         else
02799         {
02800                 return 0;
02801         }
02802 }
02803 
02804 int ED_operator_sketch_full_mode(bContext *C)
02805 {
02806         Object *obedit = CTX_data_edit_object(C);
02807         ToolSettings *ts = CTX_data_tool_settings(C);
02808 
02809         if (obedit &&
02810                 obedit->type == OB_ARMATURE &&
02811                 ts->bone_sketching & BONE_SKETCHING &&
02812                 (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0)
02813         {
02814                 return 1;
02815         }
02816         else
02817         {
02818                 return 0;
02819         }
02820 }
02821 
02822 int ED_operator_sketch_mode(const bContext *C)
02823 {
02824         Object *obedit = CTX_data_edit_object(C);
02825         ToolSettings *ts = CTX_data_tool_settings(C);
02826 
02827         if (obedit &&
02828                 obedit->type == OB_ARMATURE &&
02829                 ts->bone_sketching & BONE_SKETCHING)
02830         {
02831                 return 1;
02832         }
02833         else
02834         {
02835                 return 0;
02836         }
02837 }
02838 
02839 /* ================================================ Operators ================================================ */
02840 
02841 void SKETCH_OT_delete(wmOperatorType *ot)
02842 {
02843         /* identifiers */
02844         ot->name= "delete";
02845         ot->idname= "SKETCH_OT_delete";
02846 
02847         /* api callbacks */
02848         ot->invoke= sketch_delete;
02849 
02850         ot->poll= ED_operator_sketch_full_mode;
02851 
02852         /* flags */
02853 //      ot->flag= OPTYPE_UNDO;
02854 }
02855 
02856 void SKETCH_OT_select(wmOperatorType *ot)
02857 {
02858         /* identifiers */
02859         ot->name= "select";
02860         ot->idname= "SKETCH_OT_select";
02861 
02862         /* api callbacks */
02863         ot->invoke= sketch_select;
02864 
02865         ot->poll= ED_operator_sketch_full_mode;
02866 
02867         /* flags */
02868 //      ot->flag= OPTYPE_UNDO;
02869 }
02870 
02871 void SKETCH_OT_cancel_stroke(wmOperatorType *ot)
02872 {
02873         /* identifiers */
02874         ot->name= "cancel stroke";
02875         ot->idname= "SKETCH_OT_cancel_stroke";
02876 
02877         /* api callbacks */
02878         ot->invoke= sketch_cancel;
02879 
02880         ot->poll= ED_operator_sketch_mode_active_stroke;
02881 
02882         /* flags */
02883 //      ot->flag= OPTYPE_UNDO;
02884 }
02885 
02886 void SKETCH_OT_convert(wmOperatorType *ot)
02887 {
02888         /* identifiers */
02889         ot->name= "convert";
02890         ot->idname= "SKETCH_OT_convert";
02891 
02892         /* api callbacks */
02893         ot->invoke= sketch_convert;
02894 
02895         ot->poll= ED_operator_sketch_full_mode;
02896 
02897         /* flags */
02898         ot->flag= OPTYPE_UNDO;
02899 }
02900 
02901 void SKETCH_OT_finish_stroke(wmOperatorType *ot)
02902 {
02903         /* identifiers */
02904         ot->name= "end stroke";
02905         ot->idname= "SKETCH_OT_finish_stroke";
02906 
02907         /* api callbacks */
02908         ot->invoke= sketch_finish;
02909 
02910         ot->poll= ED_operator_sketch_mode_active_stroke;
02911 
02912         /* flags */
02913 //      ot->flag= OPTYPE_UNDO;
02914 }
02915 
02916 void SKETCH_OT_draw_preview(wmOperatorType *ot)
02917 {
02918         /* identifiers */
02919         ot->name= "draw preview";
02920         ot->idname= "SKETCH_OT_draw_preview";
02921 
02922         /* api callbacks */
02923         ot->invoke= sketch_draw_preview;
02924 
02925         ot->poll= ED_operator_sketch_mode_active_stroke;
02926 
02927         RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
02928 
02929         /* flags */
02930 //      ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
02931 }
02932 
02933 void SKETCH_OT_draw_stroke(wmOperatorType *ot)
02934 {
02935         /* identifiers */
02936         ot->name= "draw stroke";
02937         ot->idname= "SKETCH_OT_draw_stroke";
02938 
02939         /* api callbacks */
02940         ot->invoke = sketch_draw_stroke;
02941         ot->modal  = sketch_draw_stroke_modal;
02942         ot->cancel = sketch_draw_stroke_cancel;
02943 
02944         ot->poll= (int (*)(bContext *))ED_operator_sketch_mode;
02945 
02946         RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
02947 
02948         /* flags */
02949         ot->flag= OPTYPE_BLOCKING; // OPTYPE_REGISTER|OPTYPE_UNDO
02950 }
02951 
02952 void SKETCH_OT_gesture(wmOperatorType *ot)
02953 {
02954         /* identifiers */
02955         ot->name= "gesture";
02956         ot->idname= "SKETCH_OT_gesture";
02957 
02958         /* api callbacks */
02959         ot->invoke = sketch_draw_gesture;
02960         ot->modal  = sketch_draw_gesture_modal;
02961         ot->cancel = sketch_draw_gesture_cancel;
02962 
02963         ot->poll= ED_operator_sketch_mode_gesture;
02964 
02965         RNA_def_boolean(ot->srna, "snap", 0, "Snap", "");
02966 
02967         /* flags */
02968         ot->flag= OPTYPE_BLOCKING; // OPTYPE_UNDO
02969 }
02970