diff options
Diffstat (limited to 'source/blender/editors/armature/editarmature_sketch.c')
-rw-r--r-- | source/blender/editors/armature/editarmature_sketch.c | 2651 |
1 files changed, 0 insertions, 2651 deletions
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c deleted file mode 100644 index 753d4001b5d..00000000000 --- a/source/blender/editors/armature/editarmature_sketch.c +++ /dev/null @@ -1,2651 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/armature/editarmature_sketch.c - * \ingroup edarmature - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_armature_types.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" - -#include "BKE_context.h" -#include "BKE_sketch.h" -#include "BKE_layer.h" - -#include "RNA_define.h" -#include "RNA_access.h" - -#include "ED_view3d.h" -#include "ED_screen.h" - -#include "BIF_gl.h" -#include "ED_armature.h" -#include "armature_intern.h" -#include "BIF_retarget.h" -#include "BIF_generate.h" - -#include "ED_transform.h" -#include "ED_transform_snap_object_context.h" - -#include "DEG_depsgraph.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "GPU_select.h" -#include "GPU_matrix.h" -#include "GPU_batch.h" -#include "GPU_immediate.h" -#include "GPU_immediate_util.h" - -typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *); -typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *); - -typedef struct SK_GestureAction { - char name[64]; - GestureDetectFct detect; - GestureApplyFct apply; -} SK_GestureAction; - -#if 0 /* UNUSED 2.5 */ -static SK_Point boneSnap; -#endif - -static int LAST_SNAP_POINT_VALID = 0; -static float LAST_SNAP_POINT[3]; - - -typedef struct SK_StrokeIterator { - HeadFct head; - TailFct tail; - PeekFct peek; - NextFct next; - NextNFct nextN; - PreviousFct previous; - StoppedFct stopped; - - float *p, *no; - float size; - - int length; - int index; - /*********************************/ - SK_Stroke *stroke; - int start; - int end; - int stride; -} SK_StrokeIterator; - -/******************** PROTOTYPES ******************************/ - -void initStrokeIterator(BArcIterator *iter, SK_Stroke *stk, int start, int end); - -int sk_detectCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyCutGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyTrimGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyCommandGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyDeleteGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyReverseGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -int sk_detectConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); -void sk_applyConvertGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch); - -SK_Sketch *contextSketch(const bContext *c, int create); -SK_Sketch *viewcontextSketch(ViewContext *vc, int create); - -void sk_resetOverdraw(SK_Sketch *sketch); -int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk); - -/******************** GESTURE ACTIONS ******************************/ - -static SK_GestureAction GESTURE_ACTIONS[] = { - {"Cut", sk_detectCutGesture, sk_applyCutGesture}, - {"Trim", sk_detectTrimGesture, sk_applyTrimGesture}, - {"Command", sk_detectCommandGesture, sk_applyCommandGesture}, - {"Delete", sk_detectDeleteGesture, sk_applyDeleteGesture}, - {"Merge", sk_detectMergeGesture, sk_applyMergeGesture}, - {"Reverse", sk_detectReverseGesture, sk_applyReverseGesture}, - {"Convert", sk_detectConvertGesture, sk_applyConvertGesture}, - {"", NULL, NULL} -}; - -/******************** TEMPLATES UTILS *************************/ - -static char *TEMPLATES_MENU = NULL; -static int TEMPLATES_CURRENT = 0; -static GHash *TEMPLATES_HASH = NULL; -static RigGraph *TEMPLATE_RIGG = NULL; - -void BIF_makeListTemplates(const bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - ToolSettings *ts = CTX_data_tool_settings(C); - int index = 0; - - if (TEMPLATES_HASH != NULL) { - BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); - } - - TEMPLATES_HASH = BLI_ghash_int_new("makeListTemplates gh"); - TEMPLATES_CURRENT = 0; - - FOREACH_OBJECT_BEGIN(view_layer, ob) - { - if (ob != obedit && ob->type == OB_ARMATURE) { - index++; - BLI_ghash_insert(TEMPLATES_HASH, SET_INT_IN_POINTER(index), ob); - - if (ob == ts->skgen_template) { - TEMPLATES_CURRENT = index; - } - } - } - FOREACH_OBJECT_END; -} - -#if 0 /* UNUSED */ -const char *BIF_listTemplates(const bContext *UNUSED(C)) -{ - GHashIterator ghi; - const char *menu_header = IFACE_("Template %t|None %x0|"); - char *p; - const size_t template_size = (BLI_ghash_len(TEMPLATES_HASH) * 32 + 30); - - if (TEMPLATES_MENU != NULL) { - MEM_freeN(TEMPLATES_MENU); - } - - TEMPLATES_MENU = MEM_callocN(sizeof(char) * template_size, "skeleton template menu"); - - p = TEMPLATES_MENU; - p += BLI_strncpy_rlen(p, menu_header, template_size); - - BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); - - while (!BLI_ghashIterator_done(&ghi)) { - Object *ob = BLI_ghashIterator_getValue(&ghi); - int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); - - p += sprintf(p, "|%s %%x%i", ob->id.name + 2, key); - - BLI_ghashIterator_step(&ghi); - } - - return TEMPLATES_MENU; -} -#endif - -int BIF_currentTemplate(const bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - if (TEMPLATES_CURRENT == 0 && ts->skgen_template != NULL) { - GHashIterator ghi; - BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); - - while (!BLI_ghashIterator_done(&ghi)) { - Object *ob = BLI_ghashIterator_getValue(&ghi); - int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); - - if (ob == ts->skgen_template) { - TEMPLATES_CURRENT = key; - break; - } - - BLI_ghashIterator_step(&ghi); - } - } - - return TEMPLATES_CURRENT; -} - -static RigGraph *sk_makeTemplateGraph(const bContext *C, Object *ob) -{ - Object *obedit = CTX_data_edit_object(C); - if (ob == obedit) { - return NULL; - } - - if (ob != NULL) { - if (TEMPLATE_RIGG && TEMPLATE_RIGG->ob != ob) { - RIG_freeRigGraph((BGraph *)TEMPLATE_RIGG); - TEMPLATE_RIGG = NULL; - } - - if (TEMPLATE_RIGG == NULL) { - bArmature *arm; - - arm = ob->data; - - TEMPLATE_RIGG = RIG_graphFromArmature(C, ob, arm); - } - } - - return TEMPLATE_RIGG; -} - -int BIF_nbJointsTemplate(const bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - RigGraph *rg = sk_makeTemplateGraph(C, ts->skgen_template); - - if (rg) { - return RIG_nbJoints(rg); - } - else { - return -1; - } -} - -const char *BIF_nameBoneTemplate(const bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *stk = contextSketch(C, 1); - RigGraph *rg; - int index = 0; - - if (stk && stk->active_stroke != NULL) { - index = stk->active_stroke->nb_points; - } - - rg = sk_makeTemplateGraph(C, ts->skgen_template); - - if (rg == NULL) { - return ""; - } - - return RIG_nameBone(rg, 0, index); -} - -void BIF_freeTemplates(bContext *UNUSED(C)) -{ - if (TEMPLATES_MENU != NULL) { - MEM_freeN(TEMPLATES_MENU); - TEMPLATES_MENU = NULL; - } - - if (TEMPLATES_HASH != NULL) { - BLI_ghash_free(TEMPLATES_HASH, NULL, NULL); - TEMPLATES_HASH = NULL; - } - - if (TEMPLATE_RIGG != NULL) { - RIG_freeRigGraph((BGraph *)TEMPLATE_RIGG); - TEMPLATE_RIGG = NULL; - } -} - -void BIF_setTemplate(bContext *C, int index) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - if (index > 0) { - ts->skgen_template = BLI_ghash_lookup(TEMPLATES_HASH, SET_INT_IN_POINTER(index)); - } - else { - ts->skgen_template = NULL; - - if (TEMPLATE_RIGG != NULL) { - RIG_freeRigGraph((BGraph *)TEMPLATE_RIGG); - } - TEMPLATE_RIGG = NULL; - } -} - -/*********************** CONVERSION ***************************/ - -static void sk_autoname(bContext *C, ReebArc *arc) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->skgen_retarget_options & SK_RETARGET_AUTONAME) { - if (arc == NULL) { - char *num = ts->skgen_num_string; - int i = atoi(num); - i++; - BLI_snprintf(num, 8, "%i", i); - } - else { - char *side = ts->skgen_side_string; - int valid = 0; - int caps = 0; - - if (side[0] == '\0') { - valid = 1; - } - else if (STREQ(side, "R") || STREQ(side, "L")) { - valid = 1; - caps = 1; - } - else if (STREQ(side, "r") || STREQ(side, "l")) { - valid = 1; - caps = 0; - } - - if (valid) { - if (arc->head->p[0] < 0) { - BLI_snprintf(side, 8, caps ? "R" : "r"); - } - else { - BLI_snprintf(side, 8, caps ? "L" : "l"); - } - } - } - } -} - -static ReebNode *sk_pointToNode(SK_Point *pt, float imat[4][4], float tmat[3][3]) -{ - ReebNode *node; - - node = MEM_callocN(sizeof(ReebNode), "reeb node"); - copy_v3_v3(node->p, pt->p); - mul_m4_v3(imat, node->p); - - copy_v3_v3(node->no, pt->no); - mul_m3_v3(tmat, node->no); - - return node; -} - -static ReebArc *sk_strokeToArc(SK_Stroke *stk, float imat[4][4], float tmat[3][3]) -{ - ReebArc *arc; - int i; - - arc = MEM_callocN(sizeof(ReebArc), "reeb arc"); - arc->head = sk_pointToNode(stk->points, imat, tmat); - arc->tail = sk_pointToNode(sk_lastStrokePoint(stk), imat, tmat); - - arc->bcount = stk->nb_points - 2; /* first and last are nodes, don't count */ - arc->buckets = MEM_callocN(sizeof(EmbedBucket) * arc->bcount, "Buckets"); - - for (i = 0; i < arc->bcount; i++) { - copy_v3_v3(arc->buckets[i].p, stk->points[i + 1].p); - mul_m4_v3(imat, arc->buckets[i].p); - - copy_v3_v3(arc->buckets[i].no, stk->points[i + 1].no); - mul_m3_v3(tmat, arc->buckets[i].no); - } - - return arc; -} - -static void sk_retargetStroke(bContext *C, SK_Stroke *stk) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - Object *obedit = CTX_data_edit_object(C); - float imat[4][4]; - float tmat[3][3]; - ReebArc *arc; - RigGraph *rg; - - invert_m4_m4(imat, obedit->obmat); - transpose_m3_m4(tmat, obedit->obmat); - - arc = sk_strokeToArc(stk, imat, tmat); - - sk_autoname(C, arc); - - rg = sk_makeTemplateGraph(C, ts->skgen_template); - - BIF_retargetArc(C, arc, rg); - - sk_autoname(C, NULL); - - MEM_freeN(arc->head); - MEM_freeN(arc->tail); - REEB_freeArc((BArc *)arc); -} - -/**************************************************************/ -static void sk_cancelStroke(SK_Sketch *sketch) -{ - if (sketch->active_stroke != NULL) { - sk_resetOverdraw(sketch); - sk_removeStroke(sketch, sketch->active_stroke); - } -} - - -static float sk_clampPointSize(SK_Point *pt, float size) -{ - return max_ff(size * pt->size, size / 2); -} - -static void sk_drawPoint(SK_Point *pt, float size, float color[4]) -{ - Gwn_Batch *batch = NULL; - - gpuTranslate3fv(pt->p); - - gpuPushMatrix(); - - gpuScaleUniform(sk_clampPointSize(pt, size)); - - batch = GPU_batch_preset_sphere(0); - GWN_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR); - GWN_batch_uniform_4fv(batch, "color", color); - - GWN_batch_draw(batch); - - gpuPopMatrix(); -} - -static void sk_drawEdge(SK_Point *pt0, SK_Point *pt1, float size, float color[4]) -{ - float vec1[3], vec2[3] = { 0, 0, 1 }, axis[3]; - float angle, length; - - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - - sub_v3_v3v3(vec1, pt1->p, pt0->p); - length = normalize_v3(vec1); - cross_v3_v3v3(axis, vec2, vec1); - - if (is_zero_v3(axis)) { - axis[1] = 1; - } - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformColor4fv(color); - - angle = angle_normalized_v3v3(vec2, vec1); - gpuRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis); - imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8); - - immUnbindProgram(); -} - -static void sk_drawNormal(SK_Point *pt, float size, float height) -{ - float vec2[3] = { 0, 0, 1 }, axis[3]; - float angle; - float color[3] = { 0.0f, 1.0f, 1.0f }; - - Gwn_VertFormat *format = immVertexFormat(); - unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - - gpuPushMatrix(); - - cross_v3_v3v3(axis, vec2, pt->no); - - if (is_zero_v3(axis)) { - axis[1] = 1; - } - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformColor4fv(color); - - angle = angle_normalized_v3v3(vec2, pt->no); - gpuRotate3fv(angle * (float)(180.0 / M_PI), axis); - - imm_draw_cylinder_fill_3d(pos, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2); - - immUnbindProgram(); - - gpuPopMatrix(); -} - -static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end) -{ - float rgb[3]; - float zero_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - int i; - - if (id != -1) { - GPU_select_load_id(id); - - for (i = 0; i < stk->nb_points; i++) { - gpuPushMatrix(); - - sk_drawPoint(stk->points + i, 0.1, zero_color); - - if (i > 0) { - sk_drawEdge(stk->points + i - 1, stk->points + i, 0.1, zero_color); - } - - gpuPopMatrix(); - } - - } - else { - float d_rgb[3] = { 1, 1, 1 }; - float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - - copy_v3_v3(rgb, color); - sub_v3_v3(d_rgb, rgb); - mul_v3_fl(d_rgb, 1.0f / (float)stk->nb_points); - - for (i = 0; i < stk->nb_points; i++) { - SK_Point *pt = stk->points + i; - - gpuPushMatrix(); - - if (pt->type == PT_EXACT) { - sk_drawPoint(pt, 0.15, zero_color); - sk_drawNormal(pt, 0.05, 0.9); - } - - if (i >= start && i <= end) { - copy_v4_fl4(tmp_color, 0.3f, 0.3f, 0.3f, 1.0f); - } - else { - copy_v4_fl4(tmp_color, rgb[0], rgb[1], rgb[2], 1.0f); - } - - if (pt->type != PT_EXACT) { - sk_drawPoint(pt, 0.1, tmp_color); - } - - if (i > 0) { - sk_drawEdge(pt - 1, pt, 0.1, tmp_color); - } - - gpuPopMatrix(); - - add_v3_v3(rgb, d_rgb); - } - } - -} - -static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion) -{ - SK_Stroke *stk = ((SK_StrokeIterator *)iter)->stroke; - float head[3], tail[3]; - float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; - int bone_start = 0; - int end = iter->length; - int index; - - iter->head(iter); - copy_v3_v3(head, iter->p); - - index = next_subdividion(toolsettings, iter, bone_start, end, head, tail); - while (index != -1) { - SK_Point *pt = stk->points + index; - - gpuPushMatrix(); - - sk_drawPoint(pt, 0.15, color); - - sk_drawNormal(pt, 0.05, 0.9); - - gpuPopMatrix(); - - copy_v3_v3(head, tail); - bone_start = index; // start next bone from current index - - index = next_subdividion(toolsettings, iter, bone_start, end, head, tail); - } -} - -static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk) -{ - int head_index = -1; - int i; - - if (toolsettings->bone_sketching_convert == SK_CONVERT_RETARGET) { - return; - } - - - for (i = 0; i < stk->nb_points; i++) { - SK_Point *pt = stk->points + i; - - if (pt->type == PT_EXACT || i == stk->nb_points - 1) /* stop on exact or on last point */ { - if (head_index == -1) { - head_index = i; - } - else { - if (i - head_index > 1) { - SK_StrokeIterator sk_iter; - BArcIterator *iter = (BArcIterator *)&sk_iter; - - initStrokeIterator(iter, stk, head_index, i); - - if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE) { - drawSubdividedStrokeBy(toolsettings, iter, nextAdaptativeSubdivision); - } - else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - drawSubdividedStrokeBy(toolsettings, iter, nextLengthSubdivision); - } - else if (toolsettings->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - drawSubdividedStrokeBy(toolsettings, iter, nextFixedSubdivision); - } - - } - - head_index = i; - } - } - } -} - -static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], float *r_dist_px, int *index, int all_pts) -{ - ARegion *ar = CTX_wm_region(C); - SK_Point *pt = NULL; - int i; - - for (i = 0; i < stk->nb_points; i++) { - if (all_pts || stk->points[i].type == PT_EXACT) { - short pval[2]; - int pdist; - - if (ED_view3d_project_short_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *r_dist_px) { - *r_dist_px = pdist; - pt = stk->points + i; - - if (index != NULL) { - *index = i; - } - } - } - } - } - - return pt; -} - -#if 0 /* UNUSED 2.5 */ -static SK_Point *sk_snapPointArmature(bContext *C, Object *ob, ListBase *ebones, int mval[2], int *dist) -{ - ARegion *ar = CTX_wm_region(C); - SK_Point *pt = NULL; - EditBone *bone; - - for (bone = ebones->first; bone; bone = bone->next) - { - float vec[3]; - short pval[2]; - int pdist; - - if ((bone->flag & BONE_CONNECTED) == 0) - { - copy_v3_v3(vec, bone->head); - mul_m4_v3(ob->obmat, vec); - if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *dist) - { - *dist = pdist; - pt = &boneSnap; - copy_v3_v3(pt->p, vec); - pt->type = PT_EXACT; - } - } - } - - - copy_v3_v3(vec, bone->tail); - mul_m4_v3(ob->obmat, vec); - if (ED_view3d_project_short_noclip(ar, vec, pval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - - pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - - if (pdist < *dist) - { - *dist = pdist; - pt = &boneSnap; - copy_v3_v3(pt->p, vec); - pt->type = PT_EXACT; - } - } - } - - return pt; -} -#endif - -void sk_resetOverdraw(SK_Sketch *sketch) -{ - sketch->over.target = NULL; - sketch->over.start = -1; - sketch->over.end = -1; - sketch->over.count = 0; -} - -int sk_hasOverdraw(SK_Sketch *sketch, SK_Stroke *stk) -{ - return sketch->over.target && - sketch->over.count >= SK_OVERDRAW_LIMIT && - (sketch->over.target == stk || stk == NULL) && - (sketch->over.start != -1 || sketch->over.end != -1); -} - -static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - if (sketch->over.target == NULL) { - SK_Stroke *target; - int closest_index = -1; - float dist_px = SNAP_MIN_DISTANCE * 2; - - for (target = sketch->strokes.first; target; target = target->next) { - if (target != stk) { - int index; - - SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist_px, &index, 1); - - if (spt != NULL) { - sketch->over.target = target; - closest_index = index; - } - } - } - - if (sketch->over.target != NULL) { - if (closest_index > -1) { - if (sk_lastStrokePoint(stk)->type == PT_EXACT) { - sketch->over.count = SK_OVERDRAW_LIMIT; - } - else { - sketch->over.count++; - } - } - - if (stk->nb_points == 1) { - sketch->over.start = closest_index; - } - else { - sketch->over.end = closest_index; - } - } - } - else if (sketch->over.target != NULL) { - SK_Point *closest_pt = NULL; - float dist_px = SNAP_MIN_DISTANCE * 2; - int index; - - closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist_px, &index, 1); - - if (closest_pt != NULL) { - if (sk_lastStrokePoint(stk)->type == PT_EXACT) { - sketch->over.count = SK_OVERDRAW_LIMIT; - } - else { - sketch->over.count++; - } - - sketch->over.end = index; - } - else { - sketch->over.end = -1; - } - } -} - -/* return 1 on reverse needed */ -static int sk_adjustIndexes(SK_Sketch *sketch, int *start, int *end) -{ - int retval = 0; - - *start = sketch->over.start; - *end = sketch->over.end; - - if (*start == -1) { - *start = 0; - } - - if (*end == -1) { - *end = sketch->over.target->nb_points - 1; - } - - if (*end < *start) { - int tmp = *start; - *start = *end; - *end = tmp; - retval = 1; - } - - return retval; -} - -static void sk_endOverdraw(SK_Sketch *sketch) -{ - SK_Stroke *stk = sketch->active_stroke; - - if (sk_hasOverdraw(sketch, NULL)) { - int start; - int end; - - if (sk_adjustIndexes(sketch, &start, &end)) { - sk_reverseStroke(stk); - } - - if (stk->nb_points > 1) { - stk->points->type = sketch->over.target->points[start].type; - sk_lastStrokePoint(stk)->type = sketch->over.target->points[end].type; - } - - sk_insertStrokePoints(sketch->over.target, stk->points, stk->nb_points, start, end); - - sk_removeStroke(sketch, stk); - - sk_resetOverdraw(sketch); - } -} - - -static void sk_startStroke(SK_Sketch *sketch) -{ - SK_Stroke *stk = sk_createStroke(); - - BLI_addtail(&sketch->strokes, stk); - sketch->active_stroke = stk; - - sk_resetOverdraw(sketch); -} - -static void sk_endStroke(bContext *C, SK_Sketch *sketch) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - sk_shrinkStrokeBuffer(sketch->active_stroke); - - if (ts->bone_sketching & BONE_SKETCHING_ADJUST) { - sk_endOverdraw(sketch); - } - - sketch->active_stroke = NULL; -} - -static void sk_updateDrawData(SK_DrawData *dd) -{ - dd->type = PT_CONTINUOUS; - - dd->previous_mval[0] = dd->mval[0]; - dd->previous_mval[1] = dd->mval[1]; -} - -static float sk_distanceDepth(bContext *C, float p1[3], float p2[3]) -{ - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - float vec[3]; - float distance; - - sub_v3_v3v3(vec, p1, p2); - - project_v3_v3v3(vec, vec, rv3d->viewinv[2]); - - distance = len_v3(vec); - - if (dot_v3v3(rv3d->viewinv[2], vec) > 0) { - distance *= -1; - } - - return distance; -} - -static void sk_interpolateDepth(bContext *C, SK_Stroke *stk, int start, int end, float length, float distance) -{ - ARegion *ar = CTX_wm_region(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - - float progress = 0; - int i; - - progress = len_v3v3(stk->points[start].p, stk->points[start - 1].p); - - for (i = start; i <= end; i++) { - float ray_start[3], ray_normal[3]; - float delta = len_v3v3(stk->points[i].p, stk->points[i + 1].p); - float pval[2] = {0, 0}; - - ED_view3d_project_float_global(ar, stk->points[i].p, pval, V3D_PROJ_TEST_NOP); - ED_view3d_win_to_ray(CTX_data_depsgraph(C), ar, v3d, pval, ray_start, ray_normal, false); - - mul_v3_fl(ray_normal, distance * progress / length); - add_v3_v3(stk->points[i].p, ray_normal); - - progress += delta; - } -} - -static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_DrawData *dd) -{ - ARegion *ar = CTX_wm_region(C); - /* copied from grease pencil, need fixing */ - SK_Point *last = sk_lastStrokePoint(stk); - short cval[2]; - float fp[3] = {0, 0, 0}; - float dvec[3]; - float mval_f[2]; - float zfac; - - if (last != NULL) { - copy_v3_v3(fp, last->p); - } - - zfac = ED_view3d_calc_zfac(ar->regiondata, fp, NULL); - - if (ED_view3d_project_short_global(ar, fp, cval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - VECSUB2D(mval_f, cval, dd->mval); - ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); - sub_v3_v3v3(vec, fp, dvec); - } - else { - zero_v3(vec); - } -} - -static int sk_getStrokeDrawPoint(bContext *C, SK_Point *pt, SK_Sketch *UNUSED(sketch), SK_Stroke *stk, SK_DrawData *dd) -{ - pt->type = dd->type; - pt->mode = PT_PROJECT; - sk_projectDrawPoint(C, pt->p, stk, dd); - - return 1; -} - -static int sk_addStrokeDrawPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - SK_Point pt; - - sk_initPoint(&pt, dd, rv3d->viewinv[2]); - - sk_getStrokeDrawPoint(C, &pt, sketch, stk, dd); - - sk_appendStrokePoint(stk, &pt); - - return 1; -} - -static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - int point_added = 0; - - /* TODO: Since the function `ED_transform_snap_object_context_create_view3d` creates a cache, - * the ideal would be to call this function only at the beginning of the snap operation, - * or at the beginning of the operator itself */ - struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d( - CTX_data_main(C), CTX_data_scene(C), CTX_data_depsgraph(C), 0, - CTX_wm_region(C), CTX_wm_view3d(C)); - - float mvalf[2] = {UNPACK2(dd->mval)}; - float loc[3], dummy_no[3]; - - if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) { - float size; - if (peelObjectsSnapContext( - snap_context, mvalf, - &(const struct SnapObjectParams){ - .snap_select = SNAP_NOT_SELECTED, - .use_object_edit_cage = false, - }, - (ts->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, - loc, dummy_no, &size)) - { - pt->type = dd->type; - pt->mode = PT_SNAP; - pt->size = size / 2; - copy_v3_v3(pt->p, loc); - - point_added = 1; - } - } - else { - SK_Stroke *snap_stk; - float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here - - /* snap to strokes */ - // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */ - for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next) { - SK_Point *spt = NULL; - if (snap_stk == stk) { - spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 0); - } - else { - spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 1); - } - - if (spt != NULL) { - copy_v3_v3(pt->p, spt->p); - point_added = 1; - } - } - - /* try to snap to closer object */ - { - if (ED_transform_snap_object_project_view3d( - snap_context, - ts->snap_mode, - &(const struct SnapObjectParams){ - .snap_select = SNAP_NOT_SELECTED, - .use_object_edit_cage = false, - }, - mvalf, &dist_px, NULL, - loc, dummy_no)) - { - pt->type = dd->type; - pt->mode = PT_SNAP; - copy_v3_v3(pt->p, loc); - - point_added = 1; - } - } - } - - /* TODO: The ideal would be to call this function only once. - * At the end of the operator */ - ED_transform_snap_object_context_destroy(snap_context); - return point_added; -} - -static int sk_addStrokeSnapPoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd) -{ - int point_added; - ARegion *ar = CTX_wm_region(C); - RegionView3D *rv3d = ar->regiondata; - SK_Point pt; - - sk_initPoint(&pt, dd, rv3d->viewinv[2]); - - point_added = sk_getStrokeSnapPoint(C, &pt, sketch, stk, dd); - - if (point_added) { - float final_p[3]; - float length, distance; - int total; - int i; - - copy_v3_v3(final_p, pt.p); - - sk_projectDrawPoint(C, pt.p, stk, dd); - sk_appendStrokePoint(stk, &pt); - - /* update all previous point to give smooth Z progresion */ - total = 0; - length = 0; - for (i = stk->nb_points - 2; i > 0; i--) { - length += len_v3v3(stk->points[i].p, stk->points[i + 1].p); - total++; - if (stk->points[i].mode == PT_SNAP || stk->points[i].type == PT_EXACT) { - break; - } - } - - if (total > 1) { - distance = sk_distanceDepth(C, final_p, stk->points[i].p); - - sk_interpolateDepth(C, stk, i + 1, stk->nb_points - 2, length, distance); - } - - copy_v3_v3(stk->points[stk->nb_points - 1].p, final_p); - - point_added = 1; - } - - return point_added; -} - -static void sk_addStrokePoint(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, const bool snap) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - int point_added = 0; - - if (snap) { - point_added = sk_addStrokeSnapPoint(C, sketch, stk, dd); - } - - if (point_added == 0) { - point_added = sk_addStrokeDrawPoint(C, sketch, stk, dd); - } - - if (stk == sketch->active_stroke && ts->bone_sketching & BONE_SKETCHING_ADJUST) { - sk_updateOverdraw(C, sketch, stk, dd); - } -} - -static void sk_getStrokePoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, const bool snap) -{ - int point_added = 0; - - if (snap) { - point_added = sk_getStrokeSnapPoint(C, pt, sketch, stk, dd); - LAST_SNAP_POINT_VALID = 1; - copy_v3_v3(LAST_SNAP_POINT, pt->p); - } - else { - LAST_SNAP_POINT_VALID = 0; - } - - if (point_added == 0) { - point_added = sk_getStrokeDrawPoint(C, pt, sketch, stk, dd); - } -} - -/********************************************/ - -static void *headPoint(void *arg); -static void *tailPoint(void *arg); -static void *nextPoint(void *arg); -static void *nextNPoint(void *arg, int n); -static void *peekPoint(void *arg, int n); -static void *previousPoint(void *arg); -static int iteratorStopped(void *arg); - -static void initIteratorFct(SK_StrokeIterator *iter) -{ - iter->head = headPoint; - iter->tail = tailPoint; - iter->peek = peekPoint; - iter->next = nextPoint; - iter->nextN = nextNPoint; - iter->previous = previousPoint; - iter->stopped = iteratorStopped; -} - -static SK_Point *setIteratorValues(SK_StrokeIterator *iter, int index) -{ - SK_Point *pt = NULL; - - if (index >= 0 && index < iter->length) { - pt = &(iter->stroke->points[iter->start + (iter->stride * index)]); - iter->p = pt->p; - iter->no = pt->no; - iter->size = pt->size; - } - else { - iter->p = NULL; - iter->no = NULL; - iter->size = 0; - } - - return pt; -} - -void initStrokeIterator(BArcIterator *arg, SK_Stroke *stk, int start, int end) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - - initIteratorFct(iter); - iter->stroke = stk; - - if (start < end) { - iter->start = start + 1; - iter->end = end - 1; - iter->stride = 1; - } - else { - iter->start = start - 1; - iter->end = end + 1; - iter->stride = -1; - } - - iter->length = iter->stride * (iter->end - iter->start + 1); - - iter->index = -1; -} - - -static void *headPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - result = &(iter->stroke->points[iter->start - iter->stride]); - iter->p = result->p; - iter->no = result->no; - iter->size = result->size; - - return result; -} - -static void *tailPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - result = &(iter->stroke->points[iter->end + iter->stride]); - iter->p = result->p; - iter->no = result->no; - iter->size = result->size; - - return result; -} - -static void *nextPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - iter->index++; - if (iter->index < iter->length) { - result = setIteratorValues(iter, iter->index); - } - - return result; -} - -static void *nextNPoint(void *arg, int n) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - iter->index += n; - - /* check if passed end */ - if (iter->index < iter->length) { - result = setIteratorValues(iter, iter->index); - } - - return result; -} - -static void *peekPoint(void *arg, int n) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - int index = iter->index + n; - - /* check if passed end */ - if (index < iter->length) { - result = setIteratorValues(iter, index); - } - - return result; -} - -static void *previousPoint(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - SK_Point *result = NULL; - - if (iter->index > 0) { - iter->index--; - result = setIteratorValues(iter, iter->index); - } - - return result; -} - -static int iteratorStopped(void *arg) -{ - SK_StrokeIterator *iter = (SK_StrokeIterator *)arg; - - if (iter->index >= iter->length) { - return 1; - } - else { - return 0; - } -} - -static void sk_convertStroke(bContext *C, SK_Stroke *stk) -{ - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); - bArmature *arm = obedit->data; - SK_Point *head; - EditBone *parent = NULL; - float invmat[4][4]; /* move in caller function */ - float tmat[3][3]; - int head_index = 0; - int i; - - head = NULL; - - invert_m4_m4(invmat, obedit->obmat); - transpose_m3_m4(tmat, obedit->obmat); - - for (i = 0; i < stk->nb_points; i++) { - SK_Point *pt = stk->points + i; - - if (pt->type == PT_EXACT) { - if (head == NULL) { - head_index = i; - head = pt; - } - else { - EditBone *bone = NULL; - EditBone *new_parent; - - if (i - head_index > 1) { - SK_StrokeIterator sk_iter; - BArcIterator *iter = (BArcIterator *)&sk_iter; - - initStrokeIterator(iter, stk, head_index, i); - - if (ts->bone_sketching_convert == SK_CONVERT_CUT_ADAPTATIVE) { - bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextAdaptativeSubdivision); - } - else if (ts->bone_sketching_convert == SK_CONVERT_CUT_LENGTH) { - bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextLengthSubdivision); - } - else if (ts->bone_sketching_convert == SK_CONVERT_CUT_FIXED) { - bone = subdivideArcBy(ts, arm, arm->edbo, iter, invmat, tmat, nextFixedSubdivision); - } - } - - if (bone == NULL) { - bone = ED_armature_ebone_add(arm, "Bone"); - - copy_v3_v3(bone->head, head->p); - copy_v3_v3(bone->tail, pt->p); - - mul_m4_v3(invmat, bone->head); - mul_m4_v3(invmat, bone->tail); - setBoneRollFromNormal(bone, head->no, invmat, tmat); - } - - new_parent = bone; - bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL; - - /* move to end of chain */ - while (bone->parent != NULL) { - bone = bone->parent; - bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL; - } - - if (parent != NULL) { - bone->parent = parent; - bone->flag |= BONE_CONNECTED; - } - - parent = new_parent; - head_index = i; - head = pt; - } - } - } -} - -static void sk_convert(bContext *C, SK_Sketch *sketch) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Stroke *stk; - - for (stk = sketch->strokes.first; stk; stk = stk->next) { - if (stk->selected == 1) { - if (ts->bone_sketching_convert == SK_CONVERT_RETARGET) { - sk_retargetStroke(C, stk); - } - else { - sk_convertStroke(C, stk); - } -// XXX -// allqueue(REDRAWBUTSEDIT, 0); - } - } -} -/******************* GESTURE *************************/ - - -/* returns the number of self intersections */ -static int sk_getSelfIntersections(bContext *C, ListBase *list, SK_Stroke *gesture) -{ - ARegion *ar = CTX_wm_region(C); - int added = 0; - int s_i; - - for (s_i = 0; s_i < gesture->nb_points - 1; s_i++) { - float s_p1[3] = {0, 0, 0}; - float s_p2[3] = {0, 0, 0}; - int g_i; - - ED_view3d_project_float_global(ar, gesture->points[s_i].p, s_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, gesture->points[s_i + 1].p, s_p2, V3D_PROJ_TEST_NOP); - - /* start checking from second next, because two consecutive cannot intersect */ - for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++) { - float g_p1[3] = {0, 0, 0}; - float g_p2[3] = {0, 0, 0}; - float vi[3]; - float lambda; - - ED_view3d_project_float_global(ar, gesture->points[g_i].p, g_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, gesture->points[g_i + 1].p, g_p2, V3D_PROJ_TEST_NOP); - - if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { - SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); - - isect->gesture_index = g_i; - isect->before = s_i; - isect->after = s_i + 1; - isect->stroke = gesture; - - sub_v3_v3v3(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p); - mul_v3_fl(isect->p, lambda); - add_v3_v3(isect->p, gesture->points[s_i].p); - - BLI_addtail(list, isect); - - added++; - } - } - } - - return added; -} - -static int cmpIntersections(const void *i1, const void *i2) -{ - const SK_Intersection *isect1 = i1, *isect2 = i2; - - if (isect1->stroke == isect2->stroke) { - if (isect1->before < isect2->before) { - return -1; - } - else if (isect1->before > isect2->before) { - return 1; - } - else { - if (isect1->lambda < isect2->lambda) { - return -1; - } - else if (isect1->lambda > isect2->lambda) { - return 1; - } - } - } - - return 0; -} - - -/* returns the maximum number of intersections per stroke */ -static int sk_getIntersections(bContext *C, ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture) -{ - Depsgraph *depsgraph = CTX_data_depsgraph(C); - ARegion *ar = CTX_wm_region(C); - ScrArea *sa = CTX_wm_area(C); - View3D *v3d = sa->spacedata.first; - SK_Stroke *stk; - int added = 0; - - for (stk = sketch->strokes.first; stk; stk = stk->next) { - int s_added = 0; - int s_i; - - for (s_i = 0; s_i < stk->nb_points - 1; s_i++) { - float s_p1[3] = {0, 0, 0}; - float s_p2[3] = {0, 0, 0}; - int g_i; - - ED_view3d_project_float_global(ar, stk->points[s_i].p, s_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, stk->points[s_i + 1].p, s_p2, V3D_PROJ_TEST_NOP); - - for (g_i = 0; g_i < gesture->nb_points - 1; g_i++) { - float g_p1[3] = {0, 0, 0}; - float g_p2[3] = {0, 0, 0}; - float vi[3]; - float lambda; - - ED_view3d_project_float_global(ar, gesture->points[g_i].p, g_p1, V3D_PROJ_TEST_NOP); - ED_view3d_project_float_global(ar, gesture->points[g_i + 1].p, g_p2, V3D_PROJ_TEST_NOP); - - if (isect_line_line_strict_v3(s_p1, s_p2, g_p1, g_p2, vi, &lambda)) { - SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection"); - float ray_start[3], ray_end[3]; - float mval[2]; - - isect->gesture_index = g_i; - isect->before = s_i; - isect->after = s_i + 1; - isect->stroke = stk; - isect->lambda = lambda; - - mval[0] = vi[0]; - mval[1] = vi[1]; - ED_view3d_win_to_segment(depsgraph, ar, v3d, mval, ray_start, ray_end, true); - - isect_line_line_v3(stk->points[s_i].p, - stk->points[s_i + 1].p, - ray_start, - ray_end, - isect->p, - vi); - - BLI_addtail(list, isect); - - s_added++; - } - } - } - - added = MAX2(s_added, added); - } - - BLI_listbase_sort(list, cmpIntersections); - - return added; -} - -static int sk_getSegments(SK_Stroke *segments, SK_Stroke *gesture) -{ - SK_StrokeIterator sk_iter; - BArcIterator *iter = (BArcIterator *)&sk_iter; - - float CORRELATION_THRESHOLD = 0.99f; - float *vec; - int i, j; - - sk_appendStrokePoint(segments, &gesture->points[0]); - vec = segments->points[segments->nb_points - 1].p; - - initStrokeIterator(iter, gesture, 0, gesture->nb_points - 1); - - for (i = 1, j = 0; i < gesture->nb_points; i++) { - float n[3]; - - /* Calculate normal */ - sub_v3_v3v3(n, gesture->points[i].p, vec); - - if (calcArcCorrelation(iter, j, i, vec, n) < CORRELATION_THRESHOLD) { - j = i - 1; - sk_appendStrokePoint(segments, &gesture->points[j]); - vec = segments->points[segments->nb_points - 1].p; - segments->points[segments->nb_points - 1].type = PT_EXACT; - } - } - - sk_appendStrokePoint(segments, &gesture->points[gesture->nb_points - 1]); - - return segments->nb_points - 1; -} - -int sk_detectCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 1 && gest->nb_intersections == 1) { - return 1; - } - - return 0; -} - -void sk_applyCutGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Point pt; - - pt.type = PT_EXACT; - pt.mode = PT_PROJECT; /* take mode from neighboring points */ - copy_v3_v3(pt.p, isect->p); - copy_v3_v3(pt.no, isect->stroke->points[isect->before].no); - - sk_insertStrokePoint(isect->stroke, &pt, isect->after); - } -} - -int sk_detectTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 2 && gest->nb_intersections == 1 && gest->nb_self_intersections == 0) { - float s1[3], s2[3]; - float angle; - - sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p); - sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p); - - angle = RAD2DEGF(angle_v2v2(s1, s2)); - - if (angle > 60 && angle < 120) { - return 1; - } - } - - return 0; -} - -void sk_applyTrimGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - float trim_dir[3]; - - sub_v3_v3v3(trim_dir, gest->segments->points[2].p, gest->segments->points[1].p); - - for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Point pt; - float stroke_dir[3]; - - pt.type = PT_EXACT; - pt.mode = PT_PROJECT; /* take mode from neighboring points */ - copy_v3_v3(pt.p, isect->p); - copy_v3_v3(pt.no, isect->stroke->points[isect->before].no); - - sub_v3_v3v3(stroke_dir, isect->stroke->points[isect->after].p, isect->stroke->points[isect->before].p); - - /* same direction, trim end */ - if (dot_v3v3(stroke_dir, trim_dir) > 0) { - sk_replaceStrokePoint(isect->stroke, &pt, isect->after); - sk_trimStroke(isect->stroke, 0, isect->after); - } - /* else, trim start */ - else { - sk_replaceStrokePoint(isect->stroke, &pt, isect->before); - sk_trimStroke(isect->stroke, isect->before, isect->stroke->nb_points - 1); - } - - } -} - -int sk_detectCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 1) { - SK_Intersection *isect, *self_isect; - - /* get the last intersection of the first pair */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - if (isect->stroke == isect->next->stroke) { - isect = isect->next; - break; - } - } - - self_isect = gest->self_intersections.first; - - if (isect && isect->gesture_index < self_isect->gesture_index) { - return 1; - } - } - - return 0; -} - -void sk_applyCommandGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - int command = 1; - -/* XXX */ -/* command = pupmenu("Action %t|Flatten %x1|Straighten %x2|Polygonize %x3"); */ - if (command < 1) return; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - SK_Intersection *i2; - - i2 = isect->next; - - if (i2 && i2->stroke == isect->stroke) { - switch (command) { - case 1: - sk_flattenStroke(isect->stroke, isect->before, i2->after); - break; - case 2: - sk_straightenStroke(isect->stroke, isect->before, i2->after, isect->p, i2->p); - break; - case 3: - sk_polygonizeStroke(isect->stroke, isect->before, i2->after); - break; - } - - isect = i2; - } - } -} - -int sk_detectDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 2 && gest->nb_intersections == 2) { - float s1[3], s2[3]; - float angle; - - sub_v3_v3v3(s1, gest->segments->points[1].p, gest->segments->points[0].p); - sub_v3_v3v3(s2, gest->segments->points[2].p, gest->segments->points[1].p); - - angle = RAD2DEGF(angle_v2v2(s1, s2)); - - if (angle > 120) { - return 1; - } - } - - return 0; -} - -void sk_applyDeleteGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *sketch) -{ - SK_Intersection *isect; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - isect = isect->next; - - sk_removeStroke(sketch, isect->stroke); - } - } -} - -int sk_detectMergeGesture(bContext *C, SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - ARegion *ar = CTX_wm_region(C); - if (gest->nb_segments > 2 && gest->nb_intersections == 2) { - int start_val[2], end_val[2]; - int dist; - - if ((ED_view3d_project_int_global(ar, gest->stk->points[0].p, start_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) && - (ED_view3d_project_int_global(ar, sk_lastStrokePoint(gest->stk)->p, end_val, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK)) - { - dist = len_manhattan_v2v2_int(start_val, end_val); - - /* if gesture is a circle */ - if (dist <= 20) { - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - int start_index, end_index; - int i; - - start_index = MIN2(isect->after, isect->next->after); - end_index = MAX2(isect->before, isect->next->before); - - for (i = start_index; i <= end_index; i++) { - if (isect->stroke->points[i].type == PT_EXACT) { - return 1; /* at least one exact point found, stop detect here */ - } - } - - /* skip next */ - isect = isect->next; - } - } - } - } - } - - return 0; -} - -void sk_applyMergeGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only merge strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - int start_index, end_index; - int i; - - start_index = MIN2(isect->after, isect->next->after); - end_index = MAX2(isect->before, isect->next->before); - - for (i = start_index; i <= end_index; i++) { - /* if exact, switch to continuous */ - if (isect->stroke->points[i].type == PT_EXACT) { - isect->stroke->points[i].type = PT_CONTINUOUS; - } - } - - /* skip next */ - isect = isect->next; - } - } -} - -int sk_detectReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments > 2 && gest->nb_intersections == 2 && gest->nb_self_intersections == 0) { - SK_Intersection *isect; - - /* check if it circled around an exact point */ - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only delete strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - float start_v[3], end_v[3]; - float angle; - - if (isect->gesture_index < isect->next->gesture_index) { - sub_v3_v3v3(start_v, isect->p, gest->stk->points[0].p); - sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->next->p); - } - else { - sub_v3_v3v3(start_v, isect->next->p, gest->stk->points[0].p); - sub_v3_v3v3(end_v, sk_lastStrokePoint(gest->stk)->p, isect->p); - } - - angle = RAD2DEGF(angle_v2v2(start_v, end_v)); - - if (angle > 120) { - return 1; - } - - /* skip next */ - isect = isect->next; - } - } - } - - return 0; -} - -void sk_applyReverseGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - SK_Intersection *isect; - - for (isect = gest->intersections.first; isect; isect = isect->next) { - /* only reverse strokes that are crossed twice */ - if (isect->next && isect->next->stroke == isect->stroke) { - sk_reverseStroke(isect->stroke); - - /* skip next */ - isect = isect->next; - } - } -} - -int sk_detectConvertGesture(bContext *UNUSED(C), SK_Gesture *gest, SK_Sketch *UNUSED(sketch)) -{ - if (gest->nb_segments == 3 && gest->nb_self_intersections == 1) { - return 1; - } - return 0; -} - -void sk_applyConvertGesture(bContext *C, SK_Gesture *UNUSED(gest), SK_Sketch *sketch) -{ - sk_convert(C, sketch); -} - -static void sk_initGesture(bContext *C, SK_Gesture *gest, SK_Sketch *sketch) -{ - BLI_listbase_clear(&gest->intersections); - BLI_listbase_clear(&gest->self_intersections); - - gest->segments = sk_createStroke(); - gest->stk = sketch->gesture; - - gest->nb_self_intersections = sk_getSelfIntersections(C, &gest->self_intersections, gest->stk); - gest->nb_intersections = sk_getIntersections(C, &gest->intersections, sketch, gest->stk); - gest->nb_segments = sk_getSegments(gest->segments, gest->stk); -} - -static void sk_freeGesture(SK_Gesture *gest) -{ - sk_freeStroke(gest->segments); - BLI_freelistN(&gest->intersections); - BLI_freelistN(&gest->self_intersections); -} - -static void sk_applyGesture(bContext *C, SK_Sketch *sketch) -{ - SK_Gesture gest; - SK_GestureAction *act; - - sk_initGesture(C, &gest, sketch); - - /* detect and apply */ - for (act = GESTURE_ACTIONS; act->apply != NULL; act++) { - if (act->detect(C, &gest, sketch)) { - act->apply(C, &gest, sketch); - break; - } - } - - sk_freeGesture(&gest); -} - -/********************************************/ - - -static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], const bool extend) -{ - ViewContext vc; - rcti rect; - unsigned int buffer[MAXPICKBUF]; - short hits; - - ED_view3d_viewcontext_init(C, &vc); - - BLI_rcti_init_pt_radius(&rect, mval, 5); - - hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST); - - if (hits > 0) { - int besthitresult = -1; - - if (hits == 1) { - besthitresult = buffer[3]; - } - else { - besthitresult = buffer[3]; - /* loop and get best hit */ - } - - if (besthitresult > 0) { - SK_Stroke *selected_stk = BLI_findlink(&sketch->strokes, besthitresult - 1); - - if (extend == 0) { - sk_selectAllSketch(sketch, -1); - - selected_stk->selected = 1; - } - else { - selected_stk->selected ^= 1; - } - - - } - return 1; - } - - return 0; -} - -#if 0 /* UNUSED 2.5 */ -static void sk_queueRedrawSketch(SK_Sketch *sketch) -{ - if (sketch->active_stroke != NULL) - { - SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); - - if (last != NULL) - { -// XXX -// allqueue(REDRAWVIEW3D, 0); - } - } -} -#endif - -static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, int with_names) -{ - ToolSettings *ts = scene->toolsettings; - SK_Stroke *stk; - - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - - if (with_names) { - int id; - for (id = 1, stk = sketch->strokes.first; stk; id++, stk = stk->next) { - sk_drawStroke(stk, id, NULL, -1, -1); - } - - GPU_select_load_id(-1); - } - else { - float selected_rgb[3] = { 1, 0, 0 }; - float unselected_rgb[3] = { 1, 0.5, 0 }; - float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (stk = sketch->strokes.first; stk; stk = stk->next) { - int start = -1; - int end = -1; - - if (sk_hasOverdraw(sketch, stk)) { - sk_adjustIndexes(sketch, &start, &end); - } - - sk_drawStroke(stk, -1, (stk->selected == 1 ? selected_rgb : unselected_rgb), start, end); - - if (stk->selected == 1) { - sk_drawStrokeSubdivision(ts, stk); - } - } - - if (sketch->active_stroke != NULL) { - SK_Point *last = sk_lastStrokePoint(sketch->active_stroke); - - if (ts->bone_sketching & BONE_SKETCHING_QUICK) { - sk_drawStrokeSubdivision(ts, sketch->active_stroke); - } - - if (last != NULL) { - gpuPushMatrix(); - - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - - switch (sketch->next_point.mode) { - case PT_SNAP: - copy_v4_fl4(tmp_color, 0.0f, 1.0f, 0.0f, 1.0f); - break; - case PT_PROJECT: - copy_v4_fl4(tmp_color, 0.0f, 0.0f, 0.0f, 1.0f); - break; - } - - sk_drawPoint(&sketch->next_point, 0.1, tmp_color); - - copy_v4_fl4(tmp_color, selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3); - sk_drawEdge(last, &sketch->next_point, 0.1f, tmp_color); - - glDisable(GL_BLEND); - - gpuPopMatrix(); - } - } - } - - glDisable(GL_DEPTH_TEST); - - /* only draw gesture in active area */ - if (sketch->gesture != NULL /* && area_is_active_area(G.vd->area) */) { - float gesture_rgb[3] = { 0, 0.5, 1 }; - sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1); - } -} - -static int sk_finish_stroke(bContext *C, SK_Sketch *sketch) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - if (sketch->active_stroke != NULL) { - SK_Stroke *stk = sketch->active_stroke; - - sk_endStroke(C, sketch); - - if (ts->bone_sketching & BONE_SKETCHING_QUICK) { - if (ts->bone_sketching_convert == SK_CONVERT_RETARGET) { - sk_retargetStroke(C, stk); - } - else { - sk_convertStroke(C, stk); - } -// XXX -// BIF_undo_push("Convert Sketch"); - sk_removeStroke(sketch, stk); -// XXX -// allqueue(REDRAWBUTSEDIT, 0); - } - -// XXX -// allqueue(REDRAWVIEW3D, 0); - return 1; - } - - return 0; -} - -static void sk_start_draw_stroke(SK_Sketch *sketch) -{ - if (sketch->active_stroke == NULL) { - sk_startStroke(sketch); - sk_selectAllSketch(sketch, -1); - - sketch->active_stroke->selected = 1; - } -} - -static void sk_start_draw_gesture(SK_Sketch *sketch) -{ - sketch->gesture = sk_createStroke(); -} - -static int sk_draw_stroke(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK_DrawData *dd, bool snap) -{ - if (sk_stroke_filtermval(dd)) { - sk_addStrokePoint(C, sketch, stk, dd, snap); - sk_updateDrawData(dd); - sk_updateNextPoint(sketch, stk); - - return 1; - } - - return 0; -} - -static int ValidSketchViewContext(ViewContext *vc) -{ - Object *obedit = vc->obedit; - Scene *scene = vc->scene; - - if (obedit && - obedit->type == OB_ARMATURE && - scene->toolsettings->bone_sketching & BONE_SKETCHING) - { - return 1; - } - else { - return 0; - } -} - -int BDR_drawSketchNames(ViewContext *vc) -{ - if (ValidSketchViewContext(vc)) { - SK_Sketch *sketch = viewcontextSketch(vc, 0); - if (sketch) { - sk_drawSketch(vc->scene, vc->v3d, sketch, 1); - return 1; - } - } - - return 0; -} - -void BDR_drawSketch(const bContext *C) -{ - if (ED_operator_sketch_mode(C)) { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_drawSketch(CTX_data_scene(C), CTX_wm_view3d(C), sketch, 0); - } - } -} - -static int sketch_delete(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_deleteSelectedStrokes(sketch); -// allqueue(REDRAWVIEW3D, 0); - } - WM_event_add_notifier(C, NC_SCREEN | ND_SKETCH | NA_REMOVED, NULL); - return OPERATOR_FINISHED; -} - -bool BIF_sk_selectStroke(bContext *C, const int mval[2], const bool extend) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *sketch = contextSketch(C, 0); - - if (sketch != NULL && ts->bone_sketching & BONE_SKETCHING) { - if (sk_selectStroke(C, sketch, mval, extend)) { - ED_area_tag_redraw(CTX_wm_area(C)); - return true; - } - } - - return false; -} - -void BIF_convertSketch(bContext *C) -{ - if (ED_operator_sketch_full_mode(C)) { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_convert(C, sketch); -// BIF_undo_push("Convert Sketch"); -// allqueue(REDRAWVIEW3D, 0); -// allqueue(REDRAWBUTSEDIT, 0); - } - } -} - -void BIF_deleteSketch(bContext *C) -{ - if (ED_operator_sketch_full_mode(C)) { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - sk_deleteSelectedStrokes(sketch); -// BIF_undo_push("Convert Sketch"); -// allqueue(REDRAWVIEW3D, 0); - } - } -} - -#if 0 -void BIF_selectAllSketch(bContext *C, int mode) -{ - if (BIF_validSketchMode(C)) - { - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) - { - sk_selectAllSketch(sketch, mode); -// XXX -// allqueue(REDRAWVIEW3D, 0); - } - } -} -#endif - -SK_Sketch *contextSketch(const bContext *C, int create) -{ - Object *obedit = CTX_data_edit_object(C); - SK_Sketch *sketch = NULL; - - if (obedit && obedit->type == OB_ARMATURE) { - bArmature *arm = obedit->data; - - if (arm->sketch == NULL && create) { - arm->sketch = createSketch(); - } - sketch = arm->sketch; - } - - return sketch; -} - -SK_Sketch *viewcontextSketch(ViewContext *vc, int create) -{ - Object *obedit = vc->obedit; - SK_Sketch *sketch = NULL; - - if (obedit && obedit->type == OB_ARMATURE) { - bArmature *arm = obedit->data; - - if (arm->sketch == NULL && create) { - arm->sketch = createSketch(); - } - sketch = arm->sketch; - } - - return sketch; -} - -static int sketch_convert(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch != NULL) { - sk_convert(C, sketch); - ED_area_tag_redraw(CTX_wm_area(C)); - } - return OPERATOR_FINISHED; -} - -static int sketch_cancel_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch != NULL) { - sk_cancelStroke(sketch); - ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; - } - return OPERATOR_PASS_THROUGH; -} - -static int sketch_finish(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch != NULL) { - if (sk_finish_stroke(C, sketch)) { - ED_area_tag_redraw(CTX_wm_area(C)); - return OPERATOR_FINISHED; - } - } - return OPERATOR_PASS_THROUGH; -} - -static int sketch_select(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) -{ - SK_Sketch *sketch = contextSketch(C, 0); - if (sketch) { - short extend = 0; - if (sk_selectStroke(C, sketch, event->mval, extend)) - ED_area_tag_redraw(CTX_wm_area(C)); - } - - return OPERATOR_FINISHED; -} - -static void sketch_draw_stroke_cancel(bContext *C, wmOperator *op) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - sk_cancelStroke(sketch); - MEM_freeN(op->customdata); -} - -static int sketch_draw_stroke(bContext *C, wmOperator *op, const wmEvent *event) -{ - const bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_DrawData *dd; - SK_Sketch *sketch = contextSketch(C, 1); - - op->customdata = dd = MEM_callocN(sizeof(SK_DrawData), "SketchDrawData"); - sk_initDrawData(dd, event->mval); - - sk_start_draw_stroke(sketch); - - sk_draw_stroke(C, sketch, sketch->active_stroke, dd, snap); - - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; -} - -static void sketch_draw_gesture_cancel(bContext *C, wmOperator *op) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - sk_cancelStroke(sketch); - MEM_freeN(op->customdata); -} - -static int sketch_draw_gesture(bContext *C, wmOperator *op, const wmEvent *event) -{ - const bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_DrawData *dd; - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - sk_cancelStroke(sketch); - - op->customdata = dd = MEM_callocN(sizeof(SK_DrawData), "SketchDrawData"); - sk_initDrawData(dd, event->mval); - - sk_start_draw_gesture(sketch); - sk_draw_stroke(C, sketch, sketch->gesture, dd, snap); - - WM_event_add_modal_handler(C, op); - - return OPERATOR_RUNNING_MODAL; -} - -static int sketch_draw_modal(bContext *C, wmOperator *op, const wmEvent *event, short gesture, SK_Stroke *stk) -{ - bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_DrawData *dd = op->customdata; - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - int retval = OPERATOR_RUNNING_MODAL; - - switch (event->type) { - case LEFTCTRLKEY: - case RIGHTCTRLKEY: - snap = event->ctrl != 0; - RNA_boolean_set(op->ptr, "snap", snap); - break; - case MOUSEMOVE: - case INBETWEEN_MOUSEMOVE: - dd->mval[0] = event->mval[0]; - dd->mval[1] = event->mval[1]; - sk_draw_stroke(C, sketch, stk, dd, snap); - ED_area_tag_redraw(CTX_wm_area(C)); - break; - case ESCKEY: - op->type->cancel(C, op); - ED_area_tag_redraw(CTX_wm_area(C)); - retval = OPERATOR_CANCELLED; - break; - case LEFTMOUSE: - if (event->val == KM_RELEASE) { - if (gesture == 0) { - sk_endContinuousStroke(stk); - sk_filterLastContinuousStroke(stk); - sk_updateNextPoint(sketch, stk); - ED_area_tag_redraw(CTX_wm_area(C)); - MEM_freeN(op->customdata); - retval = OPERATOR_FINISHED; - } - else { - sk_endContinuousStroke(stk); - sk_filterLastContinuousStroke(stk); - - if (stk->nb_points > 1) { - /* apply gesture here */ - sk_applyGesture(C, sketch); - } - - sk_freeStroke(stk); - sketch->gesture = NULL; - - ED_area_tag_redraw(CTX_wm_area(C)); - MEM_freeN(op->customdata); - retval = OPERATOR_FINISHED; - } - } - break; - } - - return retval; -} - -static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - return sketch_draw_modal(C, op, event, 0, sketch->active_stroke); -} - -static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, const wmEvent *event) -{ - SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ - return sketch_draw_modal(C, op, event, 1, sketch->gesture); -} - -static int sketch_draw_preview(bContext *C, wmOperator *op, const wmEvent *event) -{ - const bool snap = RNA_boolean_get(op->ptr, "snap"); - SK_Sketch *sketch = contextSketch(C, 0); - - if (sketch) { - SK_DrawData dd; - - sk_initDrawData(&dd, event->mval); - sk_getStrokePoint(C, &sketch->next_point, sketch, sketch->active_stroke, &dd, snap); - ED_area_tag_redraw(CTX_wm_area(C)); - } - - return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; -} - -/* ============================================== Poll Functions ============================================= */ - -int ED_operator_sketch_mode_active_stroke(bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *sketch = contextSketch(C, 0); - - if (ts->bone_sketching & BONE_SKETCHING && - sketch != NULL && - sketch->active_stroke != NULL) - { - return 1; - } - else { - return 0; - } -} - -static int ED_operator_sketch_mode_gesture(bContext *C) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - SK_Sketch *sketch = contextSketch(C, 0); - - if (ts->bone_sketching & BONE_SKETCHING && - (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0 && - sketch != NULL && - sketch->active_stroke == NULL) - { - return 1; - } - else { - return 0; - } -} - -int ED_operator_sketch_full_mode(bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); - - if (obedit && - obedit->type == OB_ARMATURE && - ts->bone_sketching & BONE_SKETCHING && - (ts->bone_sketching & BONE_SKETCHING_QUICK) == 0) - { - return 1; - } - else { - return 0; - } -} - -int ED_operator_sketch_mode(const bContext *C) -{ - Object *obedit = CTX_data_edit_object(C); - ToolSettings *ts = CTX_data_tool_settings(C); - - if (obedit && - obedit->type == OB_ARMATURE && - ts->bone_sketching & BONE_SKETCHING) - { - return 1; - } - else { - return 0; - } -} - -/* ================================================ Operators ================================================ */ - -void SKETCH_OT_delete(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Delete"; - ot->idname = "SKETCH_OT_delete"; - ot->description = "Delete a sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_delete; - - ot->poll = ED_operator_sketch_full_mode; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select"; - ot->idname = "SKETCH_OT_select"; - ot->description = "Select a sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_select; - - ot->poll = ED_operator_sketch_full_mode; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_cancel_stroke(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Cancel Stroke"; - ot->idname = "SKETCH_OT_cancel_stroke"; - ot->description = "Cancel the current sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_cancel_invoke; - - ot->poll = ED_operator_sketch_mode_active_stroke; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_convert(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Convert"; - ot->idname = "SKETCH_OT_convert"; - ot->description = "Convert the selected sketch strokes to bone chains"; - - /* api callbacks */ - ot->invoke = sketch_convert; - - ot->poll = ED_operator_sketch_full_mode; - - /* flags */ - ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_finish_stroke(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "End Stroke"; - ot->idname = "SKETCH_OT_finish_stroke"; - ot->description = "End and keep the current sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_finish; - - ot->poll = ED_operator_sketch_mode_active_stroke; - - /* flags */ -// ot->flag = OPTYPE_UNDO; -} - -void SKETCH_OT_draw_preview(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Draw Preview"; - ot->idname = "SKETCH_OT_draw_preview"; - ot->description = "Draw preview of current sketch stroke (internal use)"; - - /* api callbacks */ - ot->invoke = sketch_draw_preview; - - ot->poll = ED_operator_sketch_mode_active_stroke; - - RNA_def_boolean(ot->srna, "snap", 0, "Snap", ""); - - /* flags */ -// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; -} - -void SKETCH_OT_draw_stroke(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Draw Stroke"; - ot->idname = "SKETCH_OT_draw_stroke"; - ot->description = "Start to draw a sketch stroke"; - - /* api callbacks */ - ot->invoke = sketch_draw_stroke; - ot->modal = sketch_draw_stroke_modal; - ot->cancel = sketch_draw_stroke_cancel; - - ot->poll = (int (*)(bContext *))ED_operator_sketch_mode; - - RNA_def_boolean(ot->srna, "snap", 0, "Snap", ""); - - /* flags */ - ot->flag = OPTYPE_BLOCKING; // OPTYPE_REGISTER|OPTYPE_UNDO -} - -void SKETCH_OT_gesture(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Gesture"; - ot->idname = "SKETCH_OT_gesture"; - ot->description = "Start to draw a gesture stroke"; - - /* api callbacks */ - ot->invoke = sketch_draw_gesture; - ot->modal = sketch_draw_gesture_modal; - ot->cancel = sketch_draw_gesture_cancel; - - ot->poll = ED_operator_sketch_mode_gesture; - - RNA_def_boolean(ot->srna, "snap", 0, "Snap", ""); - - /* flags */ - ot->flag = OPTYPE_BLOCKING; // OPTYPE_UNDO -} - |