diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-06-04 10:31:30 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-06-04 10:31:30 +0300 |
commit | 44505b38df557a5711703613685a1dec9fc2c3d9 (patch) | |
tree | 3f05bebcc7bfadf56569f2dcca7f95fc56b1b0d0 /source/blender/editors/gpencil | |
parent | 6654e109df952be3a3128fae2508a02c196ae593 (diff) |
Cleanup: strip trailing space in editors
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r-- | source/blender/editors/gpencil/drawgpencil.c | 358 | ||||
-rw-r--r-- | source/blender/editors/gpencil/editaction_gpencil.c | 152 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_brush.c | 460 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_convert.c | 324 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_data.c | 164 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_edit.c | 576 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_interpolate.c | 280 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_ops.c | 164 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_paint.c | 516 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_select.c | 324 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_undo.c | 52 | ||||
-rw-r--r-- | source/blender/editors/gpencil/gpencil_utils.c | 148 |
12 files changed, 1759 insertions, 1759 deletions
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index b23b9a06fbb..338fac03fef 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -124,15 +124,15 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn { tGPspoint *pt; int i; - + /* error checking */ if ((points == NULL) || (totpoints <= 0)) return; - + /* check if buffer can be drawn */ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) return; - + if (totpoints == 1) { /* if drawing a single point, draw it larger */ glPointSize((float)(thickness + 2) * points->pressure); @@ -146,13 +146,13 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn } else { float oldpressure = points[0].pressure; - + /* draw stroke curve */ if (G.debug & G_DEBUG) setlinestyle(2); - + glLineWidth(max_ff(oldpressure * thickness, 1.0)); glBegin(GL_LINE_STRIP); - + for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { /* if there was a significant pressure change, stop the curve, change the thickness of the stroke, * and continue drawing again (since line-width cannot change in middle of GL_LINE_STRIP) @@ -161,15 +161,15 @@ static void gp_draw_stroke_buffer(tGPspoint *points, int totpoints, short thickn glEnd(); glLineWidth(max_ff(pt->pressure * thickness, 1.0f)); glBegin(GL_LINE_STRIP); - + /* need to roll-back one point to ensure that there are no gaps in the stroke */ - if (i != 0) { + if (i != 0) { gp_set_color_and_tpoint((pt - 1), ink); } - + /* now the point we want... */ gp_set_color_and_tpoint(pt, ink); - + oldpressure = pt->pressure; } else { @@ -215,37 +215,37 @@ static void gp_draw_stroke_volumetric_buffer(tGPspoint *points, int totpoints, s { GLUquadricObj *qobj = gluNewQuadric(); float modelview[4][4]; - + tGPspoint *pt; int i; - + /* error checking */ if ((points == NULL) || (totpoints <= 0)) return; - + /* check if buffer can be drawn */ if (dflag & (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_ONLYV2D)) return; - + /* get basic matrix - should be camera space (i.e "identity") */ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview); - + /* draw points */ glPushMatrix(); - + for (i = 0, pt = points; i < totpoints; i++, pt++) { /* set the transformed position */ // TODO: scale should change based on zoom level, which requires proper translation mult too! modelview[3][0] = pt->x; modelview[3][1] = pt->y; - + glLoadMatrixf((float *)modelview); - + /* draw the disk using the current state... */ gp_set_tpoint_color(pt, ink); gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1); - - + + modelview[3][0] = modelview[3][1] = 0.0f; } @@ -263,11 +263,11 @@ static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, shor float modelview[4][4]; float baseloc[3]; float scalefac = 1.0f; - + bGPDspoint *pt; int i; float fpt[3]; - + /* HACK: We need a scale factor for the drawing in the image editor, * which seems to use 1 unit as it's maximum size, whereas everything * else assumes 1 unit = 1 pixel. Otherwise, we only get a massive blob. @@ -275,34 +275,34 @@ static void gp_draw_stroke_volumetric_2d(bGPDspoint *points, int totpoints, shor if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) { scalefac = 0.001f; } - + /* get basic matrix */ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)modelview); copy_v3_v3(baseloc, modelview[3]); - + /* draw points */ glPushMatrix(); - + for (i = 0, pt = points; i < totpoints; i++, pt++) { /* color of point */ gp_set_point_color(pt, ink); /* set the transformed position */ float co[2]; - + mul_v3_m4v3(fpt, diff_mat, &pt->x); gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); translate_m4(modelview, co[0], co[1], 0.0f); - + glLoadMatrixf((float *)modelview); - + /* draw the disk using the current state... */ gluDisk(qobj, 0.0, pt->pressure * thickness * scalefac, 32, 1); - + /* restore matrix */ copy_v3_v3(modelview[3], baseloc); } - + glPopMatrix(); gluDeleteQuadric(qobj); } @@ -313,18 +313,18 @@ static void gp_draw_stroke_volumetric_3d( short UNUSED(dflag), short UNUSED(sflag), float diff_mat[4][4], float ink[4]) { GLUquadricObj *qobj = gluNewQuadric(); - + float base_modelview[4][4], modelview[4][4]; float base_loc[3]; - + bGPDspoint *pt; int i; float fpt[3]; - + /* Get the basic modelview matrix we use for performing calculations */ glGetFloatv(GL_MODELVIEW_MATRIX, (float *)base_modelview); copy_v3_v3(base_loc, base_modelview[3]); - + /* Create the basic view-aligned billboard matrix we're going to actually draw qobj with: * - We need to knock out the rotation so that we are * simply left with a camera-facing billboard @@ -333,10 +333,10 @@ static void gp_draw_stroke_volumetric_3d( * large! */ scale_m4_fl(modelview, 0.1f); - + /* draw each point as a disk... */ glPushMatrix(); - + for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { /* color of point */ gp_set_point_color(pt, ink); @@ -345,21 +345,21 @@ static void gp_draw_stroke_volumetric_3d( /* apply translation to base_modelview, so that the translated point is put in the right place */ translate_m4(base_modelview, fpt[0], fpt[1], fpt[2]); - + /* copy the translation component to the billboard matrix we're going to use, * then reset the base matrix to the original values so that we can do the same * for the next point without accumulation/pollution effects */ copy_v3_v3(modelview[3], base_modelview[3]); /* copy offset value */ copy_v3_v3(base_modelview[3], base_loc); /* restore */ - + /* apply our billboard matrix for drawing... */ glLoadMatrixf((float *)modelview); - + /* draw the disk using the current state... */ gluDisk(qobj, 0.0, pt->pressure * thickness, 32, 1); } - + glPopMatrix(); gluDeleteQuadric(qobj); } @@ -373,40 +373,40 @@ static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d bGPDspoint *pt0 = &points[0]; bGPDspoint *pt1 = &points[1]; bGPDspoint *pt3 = &points[(int)(totpoints * 0.75)]; - + float locx[3]; float locy[3]; float loc3[3]; float normal[3]; - + /* local X axis (p0 -> p1) */ sub_v3_v3v3(locx, &pt1->x, &pt0->x); - + /* point vector at 3/4 */ sub_v3_v3v3(loc3, &pt3->x, &pt0->x); - + /* vector orthogonal to polygon plane */ cross_v3_v3v3(normal, locx, loc3); - + /* local Y axis (cross to normal/x axis) */ cross_v3_v3v3(locy, normal, locx); - + /* Normalize vectors */ normalize_v3(locx); normalize_v3(locy); - + /* Get all points in local space */ for (int i = 0; i < totpoints; i++) { bGPDspoint *pt = &points[i]; float loc[3]; - + /* Get local space using first point as origin */ sub_v3_v3v3(loc, &pt->x, &pt0->x); - + points2d[i][0] = dot_v3v3(loc, locx); points2d[i][1] = dot_v3v3(loc, locy); } - + /* Concave (-1), Convex (1), or Autodetect (0)? */ *r_direction = (int)locy[2]; } @@ -416,14 +416,14 @@ static void gp_stroke_2d_flat(bGPDspoint *points, int totpoints, float(*points2d static void gp_triangulate_stroke_fill(bGPDstroke *gps) { BLI_assert(gps->totpoints >= 3); - + /* allocate memory for temporary areas */ gps->tot_triangles = gps->totpoints - 2; unsigned int (*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation"); float (*points2d)[2] = MEM_mallocN(sizeof(*points2d) * gps->totpoints, "GP Stroke temp 2d points"); - + int direction = 0; - + /* convert to 2d and triangulate */ gp_stroke_2d_flat(gps->points, gps->totpoints, points2d, &direction); BLI_polyfill_calc(points2d, (unsigned int)gps->totpoints, direction, tmp_triangles); @@ -438,7 +438,7 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps) else { gps->triangles = MEM_recallocN(gps->triangles, sizeof(*gps->triangles) * gps->tot_triangles); } - + for (int i = 0; i < gps->tot_triangles; i++) { bGPDtriangle *stroke_triangle = &gps->triangles[i]; memcpy(stroke_triangle->verts, tmp_triangles[i], sizeof(uint[3])); @@ -448,15 +448,15 @@ static void gp_triangulate_stroke_fill(bGPDstroke *gps) /* No triangles needed - Free anything allocated previously */ if (gps->triangles) MEM_freeN(gps->triangles); - + gps->triangles = NULL; } - + /* disable recalculation flag */ if (gps->flag & GP_STROKE_RECALC_CACHES) { gps->flag &= ~GP_STROKE_RECALC_CACHES; } - + /* clear memory */ if (tmp_triangles) MEM_freeN(tmp_triangles); if (points2d) MEM_freeN(points2d); @@ -556,7 +556,7 @@ static void gp_draw_stroke_point( /* set point thickness (since there's only one of these) */ glPointSize((float)(thickness + 2) * points->pressure); - + /* get final position using parent matrix */ mul_v3_m4v3(fpt, diff_mat, &pt->x); @@ -568,10 +568,10 @@ static void gp_draw_stroke_point( } else { float co[2]; - + /* get coordinates of point */ gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co); - + /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple dot looks ok * - also mandatory in if Image Editor 'image-based' dot */ @@ -585,14 +585,14 @@ static void gp_draw_stroke_point( else { /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */ GLUquadricObj *qobj = gluNewQuadric(); - + gluQuadricDrawStyle(qobj, GLU_FILL); - + /* need to translate drawing position, but must reset after too! */ glTranslate2fv(co); gluDisk(qobj, 0.0, thickness, 32, 1); glTranslatef(-co[0], -co[1], 0.0); - + gluDeleteQuadric(qobj); } } @@ -623,14 +623,14 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness curpressure = pt->pressure; glLineWidth(max_ff(curpressure * thickness, 1.0f)); glBegin(GL_LINE_STRIP); - + /* need to roll-back one point to ensure that there are no gaps in the stroke */ - if (i != 0) { + if (i != 0) { pt2 = pt - 1; mul_v3_m4v3(fpt, diff_mat, &pt2->x); glVertex3fv(fpt); } - + /* now the point we want... */ mul_v3_m4v3(fpt, diff_mat, &pt->x); glVertex3fv(fpt); @@ -654,7 +654,7 @@ static void gp_draw_stroke_3d(bGPDspoint *points, int totpoints, short thickness /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */ if (debug) { glPointSize((float)(thickness + 2)); - + glBegin(GL_POINTS); for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { mul_v3_m4v3(fpt, diff_mat, &pt->x); @@ -673,13 +673,13 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness { /* otherwise thickness is twice that of the 3D view */ float thickness = (float)thickness_s * 0.5f; - + /* strokes in Image Editor need a scale factor, since units there are not pixels! */ float scalefac = 1.0f; if ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) { scalefac = 0.001f; } - + /* tessellation code - draw stroke as series of connected quads with connection * edges rotated to minimize shrinking artifacts, and rounded endcaps */ @@ -689,7 +689,7 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness float pm[2]; /* normal from previous segment. */ int i; float fpt[3]; - + glShadeModel(GL_FLAT); glBegin(GL_QUADS); @@ -706,17 +706,17 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness /* get x and y coordinates from point2 (point1 has already been computed in previous iteration). */ mul_v3_m4v3(fpt, diff_mat, &pt2->x); gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, s1); - + /* calculate gradient and normal - 'angle'=(ny/nx) */ m1[1] = s1[1] - s0[1]; m1[0] = s1[0] - s0[0]; normalize_v2(m1); m2[1] = -m1[0]; m2[0] = m1[1]; - + /* always use pressure from first point here */ pthick = (pt1->pressure * thickness * scalefac); - + /* color of point */ gp_set_point_color(pt1, ink); @@ -729,24 +729,24 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness mt[1] = m2[1] * pthick * 0.5f; sc[0] = s0[0] - (m1[0] * pthick * 0.75f); sc[1] = s0[1] - (m1[1] * pthick * 0.75f); - + t0[0] = sc[0] - mt[0]; t0[1] = sc[1] - mt[1]; t1[0] = sc[0] + mt[0]; t1[1] = sc[1] + mt[1]; - + glVertex2fv(t0); glVertex2fv(t1); - + /* calculate points for start of segment */ mt[0] = m2[0] * pthick; mt[1] = m2[1] * pthick; - + t0[0] = s0[0] - mt[0]; t0[1] = s0[1] - mt[1]; t1[0] = s0[0] + mt[0]; t1[1] = s0[1] + mt[1]; - + /* draw this line twice (first to finish off start cap, then for stroke) */ glVertex2fv(t1); glVertex2fv(t0); @@ -757,12 +757,12 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness else { float mb[2]; /* bisector normal */ float athick, dfac; /* actual thickness, difference between thicknesses */ - + /* calculate gradient of bisector (as average of normals) */ mb[0] = (pm[0] + m2[0]) / 2; mb[1] = (pm[1] + m2[1]) / 2; normalize_v2(mb); - + /* calculate gradient to apply * - as basis, use just pthick * bisector gradient * - if cross-section not as thick as it should be, add extra padding to fix it @@ -771,49 +771,49 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness mt[1] = mb[1] * pthick; athick = len_v2(mt); dfac = pthick - (athick * 2); - + if (((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick) == 0)) { mt[0] += (mb[0] * dfac); mt[1] += (mb[1] * dfac); } - + /* calculate points for start of segment */ t0[0] = s0[0] - mt[0]; t0[1] = s0[1] - mt[1]; t1[0] = s0[0] + mt[0]; t1[1] = s0[1] + mt[1]; - + /* draw this line twice (once for end of current segment, and once for start of next) */ glVertex2fv(t1); glVertex2fv(t0); glVertex2fv(t0); glVertex2fv(t1); } - + /* if last segment, also draw end of segment (defined as segment's normal) */ if (i == totpoints - 2) { /* for once, we use second point's pressure (otherwise it won't be drawn) */ pthick = (pt2->pressure * thickness * scalefac); - + /* color of point */ gp_set_point_color(pt2, ink); /* calculate points for end of segment */ mt[0] = m2[0] * pthick; mt[1] = m2[1] * pthick; - + t0[0] = s1[0] - mt[0]; t0[1] = s1[1] - mt[1]; t1[0] = s1[0] + mt[0]; t1[1] = s1[1] + mt[1]; - + /* draw this line twice (once for end of stroke, and once for endcap)*/ glVertex2fv(t1); glVertex2fv(t0); glVertex2fv(t0); glVertex2fv(t1); - - + + /* draw end cap as last step * - make points slightly closer to center (about halfway across) */ @@ -821,26 +821,26 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness mt[1] = m2[1] * pthick * 0.5f; sc[0] = s1[0] + (m1[0] * pthick * 0.75f); sc[1] = s1[1] + (m1[1] * pthick * 0.75f); - + t0[0] = sc[0] - mt[0]; t0[1] = sc[1] - mt[1]; t1[0] = sc[0] + mt[0]; t1[1] = sc[1] + mt[1]; - + glVertex2fv(t1); glVertex2fv(t0); } - + /* store computed point2 coordinates as point1 ones of next segment. */ copy_v2_v2(s0, s1); /* store stroke's 'natural' normal for next stroke to use */ copy_v2_v2(pm, m2); } - + glEnd(); glShadeModel(GL_SMOOTH); } - + /* draw debug points of curve on top? (original stroke points) */ if (debug) { bGPDspoint *pt; @@ -848,7 +848,7 @@ static void gp_draw_stroke_2d(bGPDspoint *points, int totpoints, short thickness float fpt[3]; glPointSize((float)(thickness_s + 2)); - + glBegin(GL_POINTS); for (i = 0, pt = points; i < totpoints && pt; i++, pt++) { float co[2]; @@ -871,24 +871,24 @@ static bool gp_can_draw_stroke(const bGPDstroke *gps, const int dflag) return false; if (!(dflag & GP_DRAWDATA_ONLY3D) && (gps->flag & GP_STROKE_3DSPACE)) return false; - + /* 2) Screen Space 2D Strokes */ if ((dflag & GP_DRAWDATA_ONLYV2D) && !(gps->flag & GP_STROKE_2DSPACE)) return false; if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) return false; - + /* 3) Image Space (2D) */ if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) return false; if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) return false; - - + + /* skip stroke if it doesn't have any valid data */ if ((gps->points == NULL) || (gps->totpoints < 1)) return false; - + /* stroke can be drawn */ return true; } @@ -1073,7 +1073,7 @@ static void gp_draw_strokes_edit( short lflag, float diff_mat[4][4], float alpha) { bGPDstroke *gps; - + /* if alpha 0 do not draw */ if (alpha == 0.0f) return; @@ -1087,7 +1087,7 @@ static void gp_draw_strokes_edit( glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); glDepthMask(0); glEnable(GL_DEPTH_TEST); - + /* first arg is normally rv3d->dist, but this isn't * available here and seems to work quite well without */ bglPolygonOffset(1.0f, 1.0f); @@ -1097,8 +1097,8 @@ static void gp_draw_strokes_edit( #endif } } - - + + /* draw stroke verts */ for (gps = gpf->strokes.first; gps; gps = gps->next) { bGPDspoint *pt; @@ -1109,14 +1109,14 @@ static void gp_draw_strokes_edit( /* check if stroke can be drawn */ if (gp_can_draw_stroke(gps, dflag) == false) continue; - + /* Optimisation: only draw points for selected strokes * We assume that selected points can only occur in * strokes that are selected too. */ if ((gps->flag & GP_STROKE_SELECT) == 0) continue; - + /* verify palette color lock */ { bGPDpalettecolor *palcolor = ED_gpencil_stroke_getcolor(gpd, gps); @@ -1143,7 +1143,7 @@ static void gp_draw_strokes_edit( else { vsize = bsize + 2; } - + /* First Pass: Draw all the verts (i.e. these become the unselected state) */ /* for now, we assume that the base color of the points is not too close to the real color */ /* set color using palette */ @@ -1151,7 +1151,7 @@ static void gp_draw_strokes_edit( glColor3fv(palcolor->color); glPointSize(bsize); - + glBegin(GL_POINTS); for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) { if (gps->flag & GP_STROKE_3DSPACE) { @@ -1166,15 +1166,15 @@ static void gp_draw_strokes_edit( } } glEnd(); - - + + /* Second Pass: Draw only verts which are selected */ float curColor[4]; UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, curColor); glColor4f(curColor[0], curColor[1], curColor[2], alpha); glPointSize(vsize); - + glBegin(GL_POINTS); for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { @@ -1184,7 +1184,7 @@ static void gp_draw_strokes_edit( } else { float co[2]; - + mul_v3_m4v3(fpt, diff_mat, &pt->x); gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co); glVertex2fv(co); @@ -1196,7 +1196,7 @@ static void gp_draw_strokes_edit( /* Draw start and end point if enabled stroke direction hint */ if ((gpd->flag & GP_DATA_SHOW_DIRECTION) && (gps->totpoints > 1)) { bGPDspoint *p; - + glPointSize(vsize + 4); glBegin(GL_POINTS); @@ -1218,14 +1218,14 @@ static void gp_draw_strokes_edit( glEnd(); } } - - + + /* clear depth mask */ if (dflag & GP_DRAWDATA_ONLY3D) { if (no_xray) { glDepthMask(mask_orig); glDisable(GL_DEPTH_TEST); - + bglPolygonOffset(0.0, 0.0); #if 0 glDisable(GL_POLYGON_OFFSET_LINE); @@ -1253,11 +1253,11 @@ static void gp_draw_onionskins( else { copy_v3_v3(color, default_color); } - + if (gpl->gstep > 0) { bGPDframe *gf; float fac; - + /* draw previous frames first */ for (gf = gpf->prev; gf; gf = gf->prev) { /* check if frame is drawable */ @@ -1283,8 +1283,8 @@ static void gp_draw_onionskins( else { /* don't draw - disabled */ } - - + + /* 2) Now draw next frames */ if (gpl->flag & GP_LAYER_GHOST_NEXTCOL) { copy_v3_v3(color, gpl->gcolor_next); @@ -1292,11 +1292,11 @@ static void gp_draw_onionskins( else { copy_v3_v3(color, default_color); } - + if (gpl->gstep_next > 0) { bGPDframe *gf; float fac; - + /* now draw next frames */ for (gf = gpf->next; gf; gf = gf->next) { /* check if frame is drawable */ @@ -1322,7 +1322,7 @@ static void gp_draw_onionskins( else { /* don't draw - disabled */ } - + } /* draw interpolate strokes (used only while operator is running) */ @@ -1339,7 +1339,7 @@ void ED_gp_draw_interpolation(tGPDinterpolate *tgpi, const int type) UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, color); color[3] = 0.6f; - int dflag = 0; + int dflag = 0; /* if 3d stuff, enable flags */ if (type == REGION_DRAW_POST_VIEW) { dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS); @@ -1373,19 +1373,19 @@ static void gp_draw_data_layers( bool debug = (gpl->flag & GP_LAYER_DRAWDEBUG) ? true : false; short lthick = brush->thickness + gpl->thickness; - + /* don't draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) continue; - + /* get frame to draw */ gpf = BKE_gpencil_layer_getframe(gpl, cfra, 0); if (gpf == NULL) continue; - + /* set basic stroke thickness */ glLineWidth(lthick); - + /* Add layer drawing settings to the set of "draw flags" * NOTE: If the setting doesn't apply, it *must* be cleared, * as dflag's carry over from the previous layer @@ -1394,10 +1394,10 @@ static void gp_draw_data_layers( if (condition) dflag |= (draw_flag_value); \ else dflag &= ~(draw_flag_value); \ } (void)0 - + /* xray... */ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_NO_XRAY), GP_DRAWDATA_NO_XRAY); - + /* volumetric strokes... */ GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_VOLUMETRIC), GP_DRAWDATA_VOLUMETRIC); @@ -1405,7 +1405,7 @@ static void gp_draw_data_layers( GP_DRAWFLAG_APPLY((gpl->flag & GP_LAYER_HQ_FILL), GP_DRAWDATA_HQ_FILL); #undef GP_DRAWFLAG_APPLY - + /* Draw 'onionskins' (frame left + right) * - It is only possible to show these if the option is enabled * - The "no onions" flag prevents ghosts from appearing during animation playback/scrubbing @@ -1413,19 +1413,19 @@ static void gp_draw_data_layers( * - The per-layer "always show" flag however overrides the playback/render restriction, * allowing artists to selectively turn onionskins on/off during playback */ - if ((gpl->flag & GP_LAYER_ONIONSKIN) && - ((dflag & GP_DRAWDATA_NO_ONIONS) == 0 || (gpl->flag & GP_LAYER_GHOST_ALWAYS))) + if ((gpl->flag & GP_LAYER_ONIONSKIN) && + ((dflag & GP_DRAWDATA_NO_ONIONS) == 0 || (gpl->flag & GP_LAYER_GHOST_ALWAYS))) { /* Drawing method - only immediately surrounding (gstep = 0), * or within a frame range on either side (gstep > 0) */ gp_draw_onionskins(gpd, gpl, gpf, offsx, offsy, winx, winy, cfra, dflag, debug, diff_mat); } - + /* draw the strokes already in active frame */ gp_draw_strokes(gpd, gpf, offsx, offsy, winx, winy, dflag, debug, gpl->thickness, gpl->opacity, gpl->tintcolor, false, false, diff_mat); - + /* Draw verts of selected strokes * - when doing OpenGL renders, we don't want to be showing these, as that ends up flickering * - locked layers can't be edited, so there's no point showing these verts @@ -1440,7 +1440,7 @@ static void gp_draw_data_layers( { gp_draw_strokes_edit(gpd, gpf, offsx, offsy, winx, winy, dflag, gpl->flag, diff_mat, alpha); } - + /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ @@ -1449,10 +1449,10 @@ static void gp_draw_data_layers( { /* Set color for drawing buffer stroke - since this may not be set yet */ // glColor4fv(gpl->color); - + /* Buffer stroke needs to be drawn with a different linestyle * to help differentiate them from normal strokes. - * + * * It should also be noted that sbuffer contains temporary point types * i.e. tGPspoints NOT bGPDspoints */ @@ -1471,25 +1471,25 @@ static void gp_draw_data_layers( static void gp_draw_status_text(bGPdata *gpd, ARegion *ar) { rcti rect; - + /* Cannot draw any status text when drawing OpenGL Renders */ if (G.f & G_RENDER_OGL) return; - + /* Get bounds of region - Necessary to avoid problems with region overlap */ ED_region_visible_rect(ar, &rect); - + /* for now, this should only be used to indicate when we are in stroke editmode */ if (gpd->flag & GP_DATA_STROKE_EDITMODE) { const char *printable = IFACE_("GPencil Stroke Editing"); float printable_size[2]; int xco, yco; - + BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - + xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; yco = (rect.ymax - U.widget_unit); - + /* text label */ UI_ThemeColor(TH_TEXT_HI); #ifdef WITH_INTERNATIONAL @@ -1497,17 +1497,17 @@ static void gp_draw_status_text(bGPdata *gpd, ARegion *ar) #else BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #endif - + /* grease pencil icon... */ // XXX: is this too intrusive? glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + xco -= U.widget_unit; yco -= (int)printable_size[1] / 2; UI_icon_draw(xco, yco, ICON_GREASEPENCIL); - + glDisable(GL_BLEND); } } @@ -1519,26 +1519,26 @@ static void gp_draw_data( { /* reset line drawing style (in case previous user didn't reset) */ setlinestyle(0); - + /* turn on smooth lines (i.e. anti-aliasing) */ glEnable(GL_LINE_SMOOTH); - - /* XXX: turn on some way of ensuring that the polygon edges get smoothed + + /* XXX: turn on some way of ensuring that the polygon edges get smoothed * GL_POLYGON_SMOOTH is nasty and shouldn't be used, as it ends up * creating internal white rays due to the ways it accumulates stuff */ - + /* turn on alpha-blending */ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - + /* draw! */ gp_draw_data_layers(brush, alpha, gpd, offsx, offsy, winx, winy, cfra, dflag); - + /* turn off alpha blending, then smooth lines */ glDisable(GL_BLEND); // alpha blending glDisable(GL_LINE_SMOOTH); // smooth lines - + /* restore initial gl conditions */ glColor4f(0, 0, 0, 1); } @@ -1575,7 +1575,7 @@ static void gp_draw_data_all(Scene *scene, bGPdata *gpd, int offsx, int offsy, i } } } - + /* scene/clip data has already been drawn, only object/track data is drawn here * if gpd_source == gpd, we don't have any object/track data and we can skip */ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) { @@ -1604,25 +1604,25 @@ void ED_gpencil_draw_2dimage(const bContext *C) bGPdata *gpd; int offsx, offsy, sizex, sizey; int dflag = GP_DRAWDATA_NOSTATUS; - + gpd = ED_gpencil_data_get_active(C); // XXX if (gpd == NULL) return; - + /* calculate rect */ switch (sa->spacetype) { case SPACE_IMAGE: /* image */ case SPACE_CLIP: /* clip */ { - + /* just draw using standard scaling (settings here are currently ignored anyways) */ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */ offsx = 0; offsy = 0; sizex = ar->winx; sizey = ar->winy; - + wmOrtho2(ar->v2d.cur.xmin, ar->v2d.cur.xmax, ar->v2d.cur.ymin, ar->v2d.cur.ymax); - + dflag |= GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_IEDITHACK; break; } @@ -1633,7 +1633,7 @@ void ED_gpencil_draw_2dimage(const bContext *C) offsy = 0; sizex = ar->winx; sizey = ar->winy; - + /* NOTE: I2D was used in 2.4x, but the old settings for that have been deprecated * and everything moved to standard View2d */ @@ -1645,19 +1645,19 @@ void ED_gpencil_draw_2dimage(const bContext *C) offsy = 0; sizex = ar->winx; sizey = ar->winy; - + dflag |= GP_DRAWDATA_ONLYI2D; break; } - + if (ED_screen_animation_playing(wm)) { /* don't show onionskins during animation playback/scrub (i.e. it obscures the poses) * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes) */ dflag |= GP_DRAWDATA_NO_ONIONS; } - - + + /* draw it! */ gp_draw_data_all(scene, gpd, offsx, offsy, sizex, sizey, CFRA, dflag, sa->spacetype); } @@ -1673,23 +1673,23 @@ void ED_gpencil_draw_view2d(const bContext *C, bool onlyv2d) Scene *scene = CTX_data_scene(C); bGPdata *gpd; int dflag = 0; - + /* check that we have grease-pencil stuff to draw */ if (sa == NULL) return; gpd = ED_gpencil_data_get_active(C); // XXX if (gpd == NULL) return; - + /* special hack for Image Editor */ /* FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled */ if (ELEM(sa->spacetype, SPACE_IMAGE, SPACE_CLIP)) dflag |= GP_DRAWDATA_IEDITHACK; - + /* draw it! */ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D | GP_DRAWDATA_NOSTATUS); if (ED_screen_animation_playing(wm)) dflag |= GP_DRAWDATA_NO_ONIONS; - + gp_draw_data_all(scene, gpd, 0, 0, ar->winx, ar->winy, CFRA, dflag, sa->spacetype); - + /* draw status text (if in screen/pixel-space) */ if (onlyv2d == false) { gp_draw_status_text(gpd, ar); @@ -1705,17 +1705,17 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg int dflag = 0; RegionView3D *rv3d = ar->regiondata; int offsx, offsy, winx, winy; - + /* check that we have grease-pencil stuff to draw */ gpd = ED_gpencil_data_get_active_v3d(scene, v3d); if (gpd == NULL) return; - + /* when rendering to the offscreen buffer we don't want to * deal with the camera border, otherwise map the coords to the camera border. */ if ((rv3d->persp == RV3D_CAMOB) && !(G.f & G_RENDER_OGL)) { rctf rectf; ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &rectf, true); /* no shift */ - + offsx = round_fl_to_int(rectf.xmin); offsy = round_fl_to_int(rectf.ymin); winx = round_fl_to_int(rectf.xmax - rectf.xmin); @@ -1727,7 +1727,7 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg winx = ar->winx; winy = ar->winy; } - + /* set flags */ if (only3d) { /* 3D strokes/3D space: @@ -1736,28 +1736,28 @@ void ED_gpencil_draw_view3d(wmWindowManager *wm, Scene *scene, View3D *v3d, AReg */ dflag |= (GP_DRAWDATA_ONLY3D | GP_DRAWDATA_NOSTATUS); } - + if (v3d->flag2 & V3D_RENDER_OVERRIDE) { /* don't draw status text when "only render" flag is set */ dflag |= GP_DRAWDATA_NOSTATUS; } - + if ((wm == NULL) || ED_screen_animation_playing(wm)) { /* don't show onionskins during animation playback/scrub (i.e. it obscures the poses) * OpenGL Renders (i.e. final output), or depth buffer (i.e. not real strokes) */ dflag |= GP_DRAWDATA_NO_ONIONS; } - + /* draw it! */ gp_draw_data_all(scene, gpd, offsx, offsy, winx, winy, CFRA, dflag, v3d->spacetype); - + } void ED_gpencil_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype) { int dflag = GP_DRAWDATA_NOSTATUS | GP_DRAWDATA_ONLYV2D; - + gp_draw_data_all(scene, gpd, 0, 0, winx, winy, cfra, dflag, spacetype); } diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 90d44503013..5e62a87caf3 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -66,18 +66,18 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *)) { bGPDframe *gpf; - + /* error checker */ if (gpl == NULL) return false; - + /* do loop */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { /* execute callback */ if (gpf_cb(gpf, scene)) return true; } - + /* nothing to return */ return false; } @@ -90,19 +90,19 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) { bGPDframe *gpf; CfraElem *ce; - + /* error checking */ if (ELEM(NULL, gpl, elems)) return; - + /* loop through gp-frames, adding */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) { ce = MEM_callocN(sizeof(CfraElem), "CfraElem"); - + ce->cfra = (float)gpf->framenum; ce->sel = (gpf->flag & GP_FRAME_SELECT) ? 1 : 0; - + BLI_addtail(elems, ce); } } @@ -115,17 +115,17 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) bool ED_gplayer_frame_select_check(bGPDlayer *gpl) { bGPDframe *gpf; - + /* error checking */ if (gpl == NULL) return false; - + /* stop at the first one found */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { if (gpf->flag & GP_FRAME_SELECT) return true; } - + /* not found */ return false; } @@ -135,7 +135,7 @@ static void gpframe_select(bGPDframe *gpf, short select_mode) { if (gpf == NULL) return; - + switch (select_mode) { case SELECT_ADD: gpf->flag |= GP_FRAME_SELECT; @@ -153,11 +153,11 @@ static void gpframe_select(bGPDframe *gpf, short select_mode) void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode) { bGPDframe *gpf; - + /* error checking */ if (gpl == NULL) return; - + /* handle according to mode */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { gpframe_select(gpf, select_mode); @@ -170,7 +170,7 @@ void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode) /* error checking */ if (gpl == NULL) return; - + /* now call the standard function */ ED_gpencil_select_frames(gpl, mode); } @@ -179,12 +179,12 @@ void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode) void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode) { bGPDframe *gpf; - + if (gpl == NULL) return; - + gpf = BKE_gpencil_layer_find_frame(gpl, selx); - + if (gpf) { gpframe_select(gpf, select_mode); } @@ -194,10 +194,10 @@ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode) void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short select_mode) { bGPDframe *gpf; - + if (gpl == NULL) return; - + /* only select those frames which are in bounds */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { if (IN_RANGE(gpf->framenum, min, max)) @@ -209,21 +209,21 @@ void ED_gplayer_frames_select_border(bGPDlayer *gpl, float min, float max, short void ED_gplayer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, short tool, short select_mode) { bGPDframe *gpf; - + if (gpl == NULL) return; - + /* only select frames which are within the region */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { /* construct a dummy point coordinate to do this testing with */ float pt[2] = {0}; - + pt[0] = gpf->framenum; pt[1] = ked->channel_y; - + /* check the necessary regions */ if (tool == BEZT_OK_CHANNEL_LASSO) { - /* Lasso */ + /* Lasso */ if (keyframe_region_lasso_test(ked->data, pt)) gpframe_select(gpf, select_mode); } @@ -243,21 +243,21 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl) { bGPDframe *gpf, *gpfn; bool changed = false; - + /* error checking */ if (gpl == NULL) return false; - + /* check for frames to delete */ for (gpf = gpl->frames.first; gpf; gpf = gpfn) { gpfn = gpf->next; - + if (gpf->flag & GP_FRAME_SELECT) { BKE_gpencil_layer_delframe(gpl, gpf); changed = true; } } - + return changed; } @@ -265,23 +265,23 @@ bool ED_gplayer_frames_delete(bGPDlayer *gpl) void ED_gplayer_frames_duplicate(bGPDlayer *gpl) { bGPDframe *gpf, *gpfn; - + /* error checking */ if (gpl == NULL) return; - + /* duplicate selected frames */ for (gpf = gpl->frames.first; gpf; gpf = gpfn) { gpfn = gpf->next; - + /* duplicate this frame */ if (gpf->flag & GP_FRAME_SELECT) { bGPDframe *gpfd; - + /* duplicate frame, and deselect self */ gpfd = BKE_gpencil_frame_duplicate(gpf); gpf->flag &= ~GP_FRAME_SELECT; - + BLI_insertlinkafter(&gpl->frames, gpf, gpfd); } } @@ -293,10 +293,10 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl) void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type) { bGPDframe *gpf; - + if (gpl == NULL) return; - + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { if (gpf->flag & GP_FRAME_SELECT) { gpf->key_type = type; @@ -327,7 +327,7 @@ void ED_gpencil_anim_copybuf_free(void) { BKE_gpencil_free_layers(&gp_anim_copybuf); BLI_listbase_clear(&gp_anim_copybuf); - + gp_anim_copy_firstframe = 999999999; gp_anim_copy_lastframe = -999999999; gp_anim_copy_cfra = 0; @@ -344,23 +344,23 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + Scene *scene = ac->scene; - - + + /* clear buffer first */ ED_gpencil_anim_copybuf_free(); - + /* filter data */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - + /* assume that each of these is a GP layer */ for (ale = anim_data.first; ale; ale = ale->next) { ListBase copied_frames = {NULL, NULL}; bGPDlayer *gpl = (bGPDlayer *)ale->data; bGPDframe *gpf; - + /* loop over frames, and copy only selected frames */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { /* if frame is selected, make duplicate it and its strokes */ @@ -368,41 +368,41 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) /* make a copy of this frame */ bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf); BLI_addtail(&copied_frames, new_frame); - + /* extend extents for keyframes encountered */ if (gpf->framenum < gp_anim_copy_firstframe) - gp_anim_copy_firstframe = gpf->framenum; + gp_anim_copy_firstframe = gpf->framenum; if (gpf->framenum > gp_anim_copy_lastframe) gp_anim_copy_lastframe = gpf->framenum; } } - + /* create a new layer in buffer if there were keyframes here */ if (BLI_listbase_is_empty(&copied_frames) == false) { bGPDlayer *new_layer = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer"); BLI_addtail(&gp_anim_copybuf, new_layer); - + /* move over copied frames */ BLI_movelisttolist(&new_layer->frames, &copied_frames); BLI_assert(copied_frames.first == NULL); - + /* make a copy of the layer's name - for name-based matching later... */ BLI_strncpy(new_layer->info, gpl->info, sizeof(new_layer->info)); } } - + /* in case 'relative' paste method is used */ gp_anim_copy_cfra = CFRA; - + /* clean up */ ANIM_animdata_freelist(&anim_data); - + /* check if anything ended up in the buffer */ if (ELEM(NULL, gp_anim_copybuf.first, gp_anim_copybuf.last)) { BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); return false; } - + /* report success */ return true; } @@ -414,22 +414,22 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - + Scene *scene = ac->scene; bool no_name = false; int offset = 0; - + /* check if buffer is empty */ if (BLI_listbase_is_empty(&gp_anim_copybuf)) { BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste"); return false; } - + /* check if single channel in buffer (disregard names if so) */ if (gp_anim_copybuf.first == gp_anim_copybuf.last) { no_name = true; } - + /* methods of offset (eKeyPasteOffset) */ switch (offset_mode) { case KEYFRAME_PASTE_OFFSET_CFRA_START: @@ -446,19 +446,19 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) break; } - + /* filter data */ // TODO: try doing it with selection, then without selection imits filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - + /* from selected channels */ for (ale = anim_data.first; ale; ale = ale->next) { bGPDlayer *gpld = (bGPDlayer *)ale->data; bGPDlayer *gpls = NULL; bGPDframe *gpfs, *gpf; - - + + /* find suitable layer from buffer to use to paste from */ for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) { /* check if layer name matches */ @@ -466,21 +466,21 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) break; } } - + /* this situation might occur! */ if (gpls == NULL) continue; - + /* add frames from buffer */ for (gpfs = gpls->frames.first; gpfs; gpfs = gpfs->next) { /* temporarily apply offset to buffer-frame while copying */ gpfs->framenum += offset; - + /* get frame to copy data into (if no frame returned, then just ignore) */ gpf = BKE_gpencil_layer_getframe(gpld, gpfs->framenum, 1); if (gpf) { bGPDstroke *gps, *gpsn; - + /* This should be the right frame... as it may be a pre-existing frame, * must make sure that only compatible stroke types get copied over * - We cannot just add a duplicate frame, as that would cause errors @@ -495,19 +495,19 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) /* duplicate triangle information */ gpsn->triangles = MEM_dupallocN(gps->triangles); /* append stroke to frame */ - BLI_addtail(&gpf->strokes, gpsn); + BLI_addtail(&gpf->strokes, gpsn); } - + /* if no strokes (i.e. new frame) added, free gpf */ if (BLI_listbase_is_empty(&gpf->strokes)) BKE_gpencil_layer_delframe(gpld, gpf); } - + /* unapply offset from buffer-frame */ gpfs->framenum -= offset; } } - + /* clean up */ ANIM_animdata_freelist(&anim_data); return true; @@ -574,37 +574,37 @@ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene) { int diff; - + if (gpf->flag & GP_FRAME_SELECT) { diff = CFRA - gpf->framenum; gpf->framenum = CFRA + diff; } - + return 0; } static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene)) { int diff; - + if (gpf->flag & GP_FRAME_SELECT) { diff = -gpf->framenum; gpf->framenum = diff; } - + return 0; } static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene)) { int diff; - + /* NOTE: since we can't really do this, we just do the same as for yaxis... */ if (gpf->flag & GP_FRAME_SELECT) { diff = -gpf->framenum; gpf->framenum = diff; } - + return 0; } @@ -613,7 +613,7 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene) static TimeMarker *marker; static short initialized = 0; int diff; - + /* In order for this mirror function to work without * any extra arguments being added, we use the case * of bezt==NULL to denote that we should find the @@ -621,7 +621,7 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene) * to use this way, as it will be set to null after * each cycle in which this is called. */ - + if (gpf) { /* mirroring time */ if ((gpf->flag & GP_FRAME_SELECT) && (marker)) { @@ -644,7 +644,7 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene) } } } - + return 0; } diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index 5fe16226421..c35b64de991 100644 --- a/source/blender/editors/gpencil/gpencil_brush.c +++ b/source/blender/editors/gpencil/gpencil_brush.c @@ -87,54 +87,54 @@ typedef struct tGP_BrushEditData { /* Current editor/region/etc. */ /* NOTE: This stuff is mainly needed to handle 3D view projection stuff... */ Scene *scene; - + ScrArea *sa; ARegion *ar; - + /* Current GPencil datablock */ bGPdata *gpd; - + /* Brush Settings */ GP_BrushEdit_Settings *settings; GP_EditBrush_Data *brush; - + eGP_EditBrush_Types brush_type; eGP_EditBrush_Flag flag; - + /* Space Conversion Data */ GP_SpaceConversion gsc; - - + + /* Is the brush currently painting? */ bool is_painting; - + /* Start of new sculpt stroke */ bool first; - + /* Current frame */ int cfra; - - + + /* Brush Runtime Data: */ /* - position and pressure * - the *_prev variants are the previous values */ int mval[2], mval_prev[2]; float pressure, pressure_prev; - + /* - effect vector (e.g. 2D/3D translation for grab brush) */ float dvec[3]; - + /* brush geometry (bounding box) */ rcti brush_rect; - + /* Custom data for certain brushes */ /* - map from bGPDstroke's to structs containing custom data about those strokes */ GHash *stroke_customdata; /* - general customdata */ void *customdata; - - + + /* Timer for in-place accumulation of brush effect */ wmTimer *timer; bool timerTick; /* is this event from a timer */ @@ -170,12 +170,12 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso) { /* The basic setting is the brush's setting (from the panel) */ bool invert = ((gso->brush->flag & GP_EDITBRUSH_FLAG_INVERT) != 0); - + /* During runtime, the user can hold down the Ctrl key to invert the basic behaviour */ if (gso->flag & GP_EDITBRUSH_FLAG_INVERT) { invert ^= true; } - + return invert; } @@ -183,26 +183,26 @@ static bool gp_brush_invert_check(tGP_BrushEditData *gso) static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, const int co[2]) { GP_EditBrush_Data *brush = gso->brush; - + /* basic strength factor from brush settings */ float influence = brush->strength; - + /* use pressure? */ if (brush->flag & GP_EDITBRUSH_FLAG_USE_PRESSURE) { influence *= gso->pressure; } - + /* distance fading */ if (brush->flag & GP_EDITBRUSH_FLAG_USE_FALLOFF) { float distance = (float)len_v2v2_int(gso->mval, co); float fac; - + CLAMP(distance, 0.0f, (float)radius); fac = 1.0f - (distance / (float)radius); - + influence *= fac; } - + /* return influence */ return influence; } @@ -241,7 +241,7 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) { gp_smooth_stroke_thickness(gps, i, inf); } - + return true; } @@ -254,13 +254,13 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in { bGPDspoint *pt = gps->points + i; float inf; - + /* Compute strength of effect * - We divide the strength by 10, so that users can set "sane" values. * Otherwise, good default values are in the range of 0.093 */ inf = gp_brush_influence_calc(gso, radius, co) / 10.0f; - + /* apply */ // XXX: this is much too strong, and it should probably do some smoothing with the surrounding stuff if (gp_brush_invert_check(gso)) { @@ -271,7 +271,7 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in /* make line thicker - increase stroke pressure */ pt->pressure += inf; } - + /* Pressure should stay within [0.0, 1.0] * However, it is nice for volumetric strokes to be able to exceed * the upper end of this range. Therefore, we don't actually clamp @@ -279,7 +279,7 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in */ if (pt->pressure < 0.0f) pt->pressure = 0.0f; - + return true; } @@ -333,7 +333,7 @@ typedef struct tGPSB_Grab_StrokeData { int *points; /* array of influence weights for each of the included points */ float *weights; - + /* capacity of the arrays */ int capacity; /* actual number of items currently stored */ @@ -344,9 +344,9 @@ typedef struct tGPSB_Grab_StrokeData { static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) { tGPSB_Grab_StrokeData *data = NULL; - + BLI_assert(gps->totpoints > 0); - + /* Check if there are buffers already (from a prior run) */ if (BLI_ghash_haskey(gso->stroke_customdata, gps)) { /* Ensure that the caches are empty @@ -355,25 +355,25 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps) */ data = BLI_ghash_lookup(gso->stroke_customdata, gps); BLI_assert(data != NULL); - + data->size = 0; /* minimum requirement - so that we can repopulate again */ - + memset(data->points, 0, sizeof(int) * data->capacity); memset(data->weights, 0, sizeof(float) * data->capacity); } else { /* Create new instance */ data = MEM_callocN(sizeof(tGPSB_Grab_StrokeData), "GP Stroke Grab Data"); - + data->capacity = gps->totpoints; data->size = 0; - + data->points = MEM_callocN(sizeof(int) * data->capacity, "GP Stroke Grab Indices"); data->weights = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Weights"); - + /* hook up to the cache */ BLI_ghash_insert(gso->stroke_customdata, gps, data); - } + } } /* store references to stroke points in the initial stage */ @@ -382,15 +382,15 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso, bGPDstroke *gps, { tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps); float inf = gp_brush_influence_calc(gso, radius, co); - + BLI_assert(data != NULL); BLI_assert(data->size < data->capacity); - + /* insert this point into the set of affected points */ data->points[data->size] = i; data->weights[data->size] = inf; data->size++; - + /* done */ return true; } @@ -406,13 +406,13 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso) RegionView3D *rv3d = gso->ar->regiondata; float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d); float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); - + float mval_f[2]; - + /* convert from 2D screenspace to 3D... */ mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]); mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]); - + ED_view3d_win_to_delta(gso->ar, mval_f, gso->dvec, zfac); } else { @@ -435,7 +435,7 @@ static void gp_brush_grab_apply_cached( for (i = 0; i < data->size; i++) { bGPDspoint *pt = &gps->points[data->points[i]]; float delta[3] = {0.0f}; - + /* adjust the amount of displacement to apply */ mul_v3_v3fl(delta, gso->dvec, data->weights[i]); if (!parented) { @@ -454,7 +454,7 @@ static void gp_brush_grab_apply_cached( invert_m4_m4(inverse_diff_mat, diff_mat); mul_m4_v3(inverse_diff_mat, &pt->x); } - + } } @@ -462,11 +462,11 @@ static void gp_brush_grab_apply_cached( static void gp_brush_grab_stroke_free(void *ptr) { tGPSB_Grab_StrokeData *data = (tGPSB_Grab_StrokeData *)ptr; - + /* free arrays */ MEM_freeN(data->points); MEM_freeN(data->weights); - + /* ... and this item itself, since it was also allocated */ MEM_freeN(data); } @@ -481,10 +481,10 @@ static bool gp_brush_push_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, bGPDspoint *pt = gps->points + i; float inf = gp_brush_influence_calc(gso, radius, co); float delta[3] = {0.0f}; - + /* adjust the amount of displacement to apply */ mul_v3_v3fl(delta, gso->dvec, inf); - + /* apply */ add_v3_v3(&pt->x, delta); @@ -506,12 +506,12 @@ static void gp_brush_calc_midpoint(tGP_BrushEditData *gso) RegionView3D *rv3d = gso->ar->regiondata; float *rvec = ED_view3d_cursor3d_get(gso->scene, v3d); float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); - + float mval_f[2] = {UNPACK2(gso->mval)}; float mval_prj[2]; float dvec[3]; - - + + if (ED_view3d_project_float_global(gso->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { sub_v2_v2v2(mval_f, mval_prj, mval_f); ED_view3d_win_to_delta(gso->ar, mval_f, dvec, zfac); @@ -537,17 +537,17 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, bGPDspoint *pt = gps->points + i; float fac, inf; float vec[3]; - + /* Scale down standard influence value to get it more manageable... * - No damping = Unmanageable at > 0.5 strength * - Div 10 = Not enough effect * - Div 5 = Happy medium... (by trial and error) */ inf = gp_brush_influence_calc(gso, radius, co) / 5.0f; - + /* 1) Make this point relative to the cursor/midpoint (dvec) */ sub_v3_v3v3(vec, &pt->x, gso->dvec); - + /* 2) Shrink the distance by pulling the point towards the midpoint * (0.0 = at midpoint, 1 = at edge of brush region) * OR @@ -562,10 +562,10 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, fac = 1.0f - (inf * inf); /* squared to temper the effect... */ } mul_v3_fl(vec, fac); - + /* 3) Translate back to original space, with the shrinkage applied */ add_v3_v3v3(&pt->x, gso->dvec, vec); - + /* done */ return true; } @@ -582,16 +582,16 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, { bGPDspoint *pt = gps->points + i; float angle, inf; - + /* Angle to rotate by */ inf = gp_brush_influence_calc(gso, radius, co); angle = DEG2RADF(1.0f) * inf; - + if (gp_brush_invert_check(gso)) { /* invert angle that we rotate by */ angle *= -1; } - + /* Rotate in 2D or 3D space? */ if (gps->flag & GP_STROKE_3DSPACE) { /* Perform rotation in 3D space... */ @@ -599,13 +599,13 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, float rmat[3][3]; float axis[3]; float vec[3]; - + /* Compute rotation matrix - rotate around view vector by angle */ negate_v3_v3(axis, rv3d->persinv[2]); normalize_v3(axis); - + axis_angle_normalized_to_mat3(rmat, axis, angle); - + /* Rotate point (no matrix-space transforms needed, as GP points are in world space) */ sub_v3_v3v3(vec, &pt->x, gso->dvec); /* make relative to center (center is stored in dvec) */ mul_m3_v3(rmat, vec); @@ -615,20 +615,20 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, const float axis[3] = {0.0f, 0.0f, 1.0f}; float vec[3] = {0.0f}; float rmat[3][3]; - + /* Express position of point relative to cursor, ready to rotate */ // XXX: There is still some offset here, but it's close to working as expected... vec[0] = (float)(co[0] - gso->mval[0]); vec[1] = (float)(co[1] - gso->mval[1]); - + /* rotate point */ axis_angle_normalized_to_mat3(rmat, axis, angle); mul_m3_v3(rmat, vec); - + /* Convert back to screen-coordinates */ vec[0] += (float)gso->mval[0]; vec[1] += (float)gso->mval[1]; - + /* Map from screen-coordinates to final coordinate space */ if (gps->flag & GP_STROKE_2DSPACE) { View2D *v2d = gso->gsc.v2d; @@ -639,7 +639,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i, copy_v2_v2(&pt->x, vec); } } - + /* done */ return true; } @@ -653,7 +653,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in const int radius, const int co[2]) { bGPDspoint *pt = gps->points + i; - + /* Amount of jitter to apply depends on the distance of the point to the cursor, * as well as the strength of the brush */ @@ -766,13 +766,13 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in typedef struct tGPSB_CloneBrushData { /* midpoint of the strokes on the clipboard */ float buffer_midpoint[3]; - + /* number of strokes in the paste buffer (and/or to be created each time) */ size_t totitems; - + /* for "stamp" mode, the currently pasted brushes */ bGPDstroke **new_strokes; - + /* mapping from colors referenced per stroke, to the new colours in the "pasted" strokes */ GHash *new_colors; } tGPSB_CloneBrushData; @@ -782,43 +782,43 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data; bGPDstroke *gps; - + /* init custom data */ gso->customdata = data = MEM_callocN(sizeof(tGPSB_CloneBrushData), "CloneBrushData"); - + /* compute midpoint of strokes on clipboard */ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { const float dfac = 1.0f / ((float)gps->totpoints); float mid[3] = {0.0f}; - + bGPDspoint *pt; int i; - + /* compute midpoint of this stroke */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { float co[3]; - + mul_v3_v3fl(co, &pt->x, dfac); add_v3_v3(mid, co); } - + /* combine this stroke's data with the main data */ add_v3_v3(data->buffer_midpoint, mid); data->totitems++; } } - + /* Divide the midpoint by the number of strokes, to finish averaging it */ if (data->totitems > 1) { mul_v3_fl(data->buffer_midpoint, 1.0f / (float)data->totitems); } - + /* Create a buffer for storing the current strokes */ if (1 /*gso->brush->mode == GP_EDITBRUSH_CLONE_MODE_STAMP*/) { data->new_strokes = MEM_callocN(sizeof(bGPDstroke *) * data->totitems, "cloned strokes ptr array"); } - + /* Init colormap for mapping between the pasted stroke's source colour(names) * and the final colours that will be used here instead... */ @@ -829,19 +829,19 @@ static void gp_brush_clone_init(bContext *C, tGP_BrushEditData *gso) static void gp_brush_clone_free(tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data = gso->customdata; - + /* free strokes array */ if (data->new_strokes) { MEM_freeN(data->new_strokes); data->new_strokes = NULL; } - + /* free copybuf colormap */ if (data->new_colors) { BLI_ghash_free(data->new_colors, NULL, NULL); data->new_colors = NULL; } - + /* free the customdata itself */ MEM_freeN(data); gso->customdata = NULL; @@ -851,44 +851,44 @@ static void gp_brush_clone_free(tGP_BrushEditData *gso) static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data = gso->customdata; - + Scene *scene = gso->scene; bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true); bGPDstroke *gps; - + float delta[3]; size_t strokes_added = 0; - + /* Compute amount to offset the points by */ /* NOTE: This assumes that screenspace strokes are NOT used in the 3D view... */ - + gp_brush_calc_midpoint(gso); /* this puts the cursor location into gso->dvec */ sub_v3_v3v3(delta, gso->dvec, data->buffer_midpoint); - + /* Copy each stroke into the layer */ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { bGPDstroke *new_stroke; bGPDspoint *pt; int i; - + /* Make a new stroke */ new_stroke = MEM_dupallocN(gps); - + new_stroke->points = MEM_dupallocN(gps->points); new_stroke->triangles = MEM_dupallocN(gps->triangles); - + new_stroke->next = new_stroke->prev = NULL; BLI_addtail(&gpf->strokes, new_stroke); - + /* Fix color references */ BLI_assert(new_stroke->colorname[0] != '\0'); new_stroke->palcolor = BLI_ghash_lookup(data->new_colors, new_stroke->colorname); - + BLI_assert(new_stroke->palcolor != NULL); BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname)); - + /* Adjust all the stroke's points, so that the strokes * get pasted relative to where the cursor is now */ @@ -896,7 +896,7 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso) /* assume that the delta can just be applied, and then everything works */ add_v3_v3(&pt->x, delta); } - + /* Store ref for later */ if ((data->new_strokes) && (strokes_added < data->totitems)) { data->new_strokes[strokes_added] = new_stroke; @@ -911,31 +911,31 @@ static void gp_brush_clone_adjust(tGP_BrushEditData *gso) { tGPSB_CloneBrushData *data = gso->customdata; size_t snum; - + /* Compute the amount of movement to apply (overwrites dvec) */ gp_brush_grab_calc_dvec(gso); - + /* For each of the stored strokes, apply the offset to each point */ /* NOTE: Again this assumes that in the 3D view, we only have 3d space and not screenspace strokes... */ for (snum = 0; snum < data->totitems; snum++) { bGPDstroke *gps = data->new_strokes[snum]; bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (gso->brush->flag & GP_EDITBRUSH_FLAG_USE_FALLOFF) { /* "Smudge" Effect when falloff is enabled */ float delta[3] = {0.0f}; int sco[2] = {0}; float influence; - + /* compute influence on point */ gp_point_to_xy(&gso->gsc, gps, pt, &sco[0], &sco[1]); influence = gp_brush_influence_calc(gso, gso->brush->size, sco); - + /* adjust the amount of displacement to apply */ mul_v3_v3fl(delta, gso->dvec, influence); - + /* apply */ add_v3_v3(&pt->x, delta); } @@ -967,7 +967,7 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) gp_brush_clone_add(C, gso); } } - + return true; } @@ -978,27 +978,27 @@ static bool gpsculpt_brush_apply_clone(bContext *C, tGP_BrushEditData *gso) static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)) { GP_EditBrush_Data *brush = gpsculpt_get_brush(CTX_data_scene(C)); - + if (brush) { glPushMatrix(); - + glTranslatef((float)x, (float)y, 0.0f); - + glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - + /* Inner Ring: Light color for action of the brush */ /* TODO: toggle between add and remove? */ glColor4ub(255, 255, 255, 200); glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size, 40); - + /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */ glColor3ub(30, 30, 30); glutil_draw_lined_arc(0.0, M_PI * 2.0, brush->size + 1, 40); - + glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - + glPopMatrix(); } } @@ -1007,7 +1007,7 @@ static void gp_brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customda static void gpencil_toggle_brush_cursor(bContext *C, bool enable) { GP_BrushEdit_Settings *gset = gpsculpt_get_settings(CTX_data_scene(C)); - + if (gset->paintcursor && !enable) { /* clear cursor */ WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); @@ -1015,8 +1015,8 @@ static void gpencil_toggle_brush_cursor(bContext *C, bool enable) } else if (enable) { /* enable cursor */ - gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), - NULL, + gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), + NULL, gp_brush_drawcursor, NULL); } } @@ -1029,15 +1029,15 @@ static void gpsculpt_brush_header_set(bContext *C, tGP_BrushEditData *gso) { const char *brush_name = NULL; char str[UI_MAX_DRAW_STR] = ""; - + RNA_enum_name(rna_enum_gpencil_sculpt_brush_items, gso->brush_type, &brush_name); - + BLI_snprintf(str, sizeof(str), IFACE_("GPencil Sculpt: %s Stroke | LMB to paint | RMB/Escape to Exit" " | Ctrl to Invert Action | Wheel Up/Down for Size " " | Shift-Wheel Up/Down for Strength"), (brush_name) ? brush_name : "<?>"); - + ED_area_headerprint(CTX_wm_area(C), str); } @@ -1050,36 +1050,36 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); tGP_BrushEditData *gso; - + /* setup operator data */ gso = MEM_callocN(sizeof(tGP_BrushEditData), "tGP_BrushEditData"); op->customdata = gso; - + /* store state */ gso->settings = gpsculpt_get_settings(scene); gso->brush = gpsculpt_get_brush(scene); - + gso->brush_type = gso->settings->brushtype; - - + + gso->is_painting = false; gso->first = true; - + gso->gpd = ED_gpencil_data_get_active(C); gso->cfra = INT_MAX; /* NOTE: So that first stroke will get handled in init_stroke() */ - + gso->scene = scene; - + gso->sa = CTX_wm_area(C); gso->ar = CTX_wm_region(C); - + /* initialise custom data for brushes */ switch (gso->brush_type) { case GP_EDITBRUSH_TYPE_CLONE: { bGPDstroke *gps; bool found = false; - + /* check that there are some usable strokes in the buffer */ for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { @@ -1087,12 +1087,12 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) break; } } - + if (found == false) { /* STOP HERE! Nothing to paste! */ - BKE_report(op->reports, RPT_ERROR, + BKE_report(op->reports, RPT_ERROR, "Copy some strokes to the clipboard before using the Clone brush to paste copies of them"); - + MEM_freeN(gso); op->customdata = NULL; return false; @@ -1103,30 +1103,30 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op) } break; } - + case GP_EDITBRUSH_TYPE_GRAB: { /* initialise the cache needed for this brush */ gso->stroke_customdata = BLI_ghash_ptr_new("GP Grab Brush - Strokes Hash"); break; } - + /* Others - No customdata needed */ default: break; } - - + + /* setup space conversions */ gp_point_conversion_init(C, &gso->gsc); - + /* update header */ gpsculpt_brush_header_set(C, gso); - + /* setup cursor drawing */ WM_cursor_modal_set(CTX_wm_window(C), BC_CROSSCURSOR); gpencil_toggle_brush_cursor(C, true); - + return true; } @@ -1134,7 +1134,7 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op) { tGP_BrushEditData *gso = op->customdata; wmWindow *win = CTX_wm_window(C); - + /* free brush-specific data */ switch (gso->brush_type) { case GP_EDITBRUSH_TYPE_GRAB: @@ -1146,18 +1146,18 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op) BLI_ghash_free(gso->stroke_customdata, NULL, gp_brush_grab_stroke_free); break; } - + case GP_EDITBRUSH_TYPE_CLONE: { /* Free customdata */ gp_brush_clone_free(gso); break; } - + default: break; } - + /* unregister timer (only used for realtime) */ if (gso->timer) { WM_event_remove_timer(CTX_wm_manager(C), win, gso->timer); @@ -1167,7 +1167,7 @@ static void gpsculpt_brush_exit(bContext *C, wmOperator *op) ED_area_headerprint(CTX_wm_area(C), NULL); WM_cursor_modal_restore(win); gpencil_toggle_brush_cursor(C, false); - + /* free operator data */ MEM_freeN(gso); op->customdata = NULL; @@ -1188,18 +1188,18 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso) bGPdata *gpd = gso->gpd; bGPDlayer *gpl; int cfra = CFRA; - + /* only try to add a new frame if this is the first stroke, or the frame has changed */ if ((gpd == NULL) || (cfra == gso->cfra)) return; - + /* go through each layer, and ensure that we've got a valid frame to use */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; - - /* Make a new frame to work on if the layer's frame and the current scene frame don't match up + + /* Make a new frame to work on if the layer's frame and the current scene frame don't match up * - This is useful when animating as it saves that "uh-oh" moment when you realize you've * spent too much time editing the wrong frame... */ @@ -1209,7 +1209,7 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso) } } } - + /* save off new current frame, so that next update works fine */ gso->cfra = cfra; } @@ -1224,7 +1224,7 @@ static bool gpsculpt_brush_do_stroke( GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; const int radius = gso->brush->size; - + bGPDspoint *pt1, *pt2; int pc1[2] = {0}; int pc2[2] = {0}; @@ -1241,7 +1241,7 @@ static bool gpsculpt_brush_do_stroke( gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); gp_point_to_xy(gsc, gps, &pt_temp, &pc1[0], &pc1[1]); } - + /* do boundbox check first */ if ((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) { /* only check if point is inside */ @@ -1252,14 +1252,14 @@ static bool gpsculpt_brush_do_stroke( } } else { - /* Loop over the points in the stroke, checking for intersections + /* Loop over the points in the stroke, checking for intersections * - an intersection means that we touched the stroke */ for (i = 0; (i + 1) < gps->totpoints; i++) { /* Get points to work with */ pt1 = gps->points + i; pt2 = gps->points + i + 1; - + /* Skip if neither one is selected (and we are only allowed to edit/consider selected points) */ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_SELECT_MASK) { if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) { @@ -1292,14 +1292,14 @@ static bool gpsculpt_brush_do_stroke( if (gp_stroke_inside_circle(gso->mval, gso->mval_prev, radius, pc1[0], pc1[1], pc2[0], pc2[1])) { /* Apply operation to these points */ bool ok = false; - + /* To each point individually... */ ok = apply(gso, gps, i, radius, pc1); - + /* Only do the second point if this is the last segment, * and it is unlikely that the point will get handled - * otherwise. - * + * otherwise. + * * NOTE: There is a small risk here that the second point wasn't really * actually in-range. In that case, it only got in because * the line linking the points was! @@ -1311,13 +1311,13 @@ static bool gpsculpt_brush_do_stroke( else { include_last = true; } - + changed |= ok; } else if (include_last) { /* This case is for cases where for whatever reason the second vert (1st here) doesn't get included * because the whole edge isn't in bounds, but it would've qualified since it did with the - * previous step (but wasn't added then, to avoid double-ups) + * previous step (but wasn't added then, to avoid double-ups) */ changed |= apply(gso, gps, i, radius, pc1); include_last = false; @@ -1325,7 +1325,7 @@ static bool gpsculpt_brush_do_stroke( } } } - + return changed; } @@ -1333,7 +1333,7 @@ static bool gpsculpt_brush_do_stroke( static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) { bool changed = false; - + /* Calculate brush-specific data which applies equally to all points */ switch (gso->brush_type) { case GP_EDITBRUSH_TYPE_GRAB: /* Grab points */ @@ -1343,7 +1343,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) gp_brush_grab_calc_dvec(gso); break; } - + case GP_EDITBRUSH_TYPE_PINCH: /* Pinch points */ case GP_EDITBRUSH_TYPE_TWIST: /* Twist points around midpoint */ { @@ -1351,19 +1351,19 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) gp_brush_calc_midpoint(gso); break; } - + case GP_EDITBRUSH_TYPE_RANDOMIZE: /* Random jitter */ { /* compute the displacement vector for the cursor (in data space) */ gp_brush_grab_calc_dvec(gso); break; } - + default: break; } - - + + /* Find visible strokes, and perform operations on those if hit */ float diff_mat[4][4]; bool parented = false; @@ -1373,7 +1373,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) bGPDframe *gpf = gpl->actframe; if (gpf == NULL) continue; - + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); @@ -1382,7 +1382,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso) else { parented = false; } - + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) @@ -1477,34 +1477,34 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt float mousef[2]; int mouse[2]; bool changed = false; - + /* Get latest mouse coordinates */ RNA_float_get_array(itemptr, "mouse", mousef); gso->mval[0] = mouse[0] = (int)(mousef[0]); gso->mval[1] = mouse[1] = (int)(mousef[1]); - + gso->pressure = RNA_float_get(itemptr, "pressure"); - + if (RNA_boolean_get(itemptr, "pen_flip")) gso->flag |= GP_EDITBRUSH_FLAG_INVERT; else gso->flag &= ~GP_EDITBRUSH_FLAG_INVERT; - - + + /* Store coordinates as reference, if operator just started running */ if (gso->first) { gso->mval_prev[0] = gso->mval[0]; gso->mval_prev[1] = gso->mval[1]; gso->pressure_prev = gso->pressure; } - + /* Update brush_rect, so that it represents the bounding rectangle of brush */ gso->brush_rect.xmin = mouse[0] - radius; gso->brush_rect.ymin = mouse[1] - radius; gso->brush_rect.xmax = mouse[0] + radius; gso->brush_rect.ymax = mouse[1] + radius; - - + + /* Apply brush */ if (gso->brush_type == GP_EDITBRUSH_TYPE_CLONE) { changed = gpsculpt_brush_apply_clone(C, gso); @@ -1512,13 +1512,13 @@ static void gpsculpt_brush_apply(bContext *C, wmOperator *op, PointerRNA *itempt else { changed = gpsculpt_brush_apply_standard(C, gso); } - - + + /* Updates */ if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } - + /* Store values for next step */ gso->mval_prev[0] = gso->mval[0]; gso->mval_prev[1] = gso->mval[1]; @@ -1535,24 +1535,24 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven PointerRNA itemptr; float mouse[2]; int tablet = 0; - + mouse[0] = event->mval[0] + 1; mouse[1] = event->mval[1] + 1; - + /* fill in stroke */ RNA_collection_add(op->ptr, "stroke", &itemptr); - + RNA_float_set_array(&itemptr, "mouse", mouse); RNA_boolean_set(&itemptr, "pen_flip", event->ctrl != false); RNA_boolean_set(&itemptr, "is_start", gso->first); - + /* handle pressure sensitivity (which is supplied by tablets) */ if (event->tablet_data) { const wmTabletData *wmtab = event->tablet_data; float pressure = wmtab->Pressure; - + tablet = (wmtab->Active != EVT_TABLET_NONE); - + /* special exception here for too high pressure values on first touch in * windows for some tablets: clamp the values to be sane */ @@ -1564,7 +1564,7 @@ static void gpsculpt_brush_apply_event(bContext *C, wmOperator *op, const wmEven else { RNA_float_set(&itemptr, "pressure", 1.0f); } - + /* apply */ gpsculpt_brush_apply(C, op, &itemptr); } @@ -1574,15 +1574,15 @@ static int gpsculpt_brush_exec(bContext *C, wmOperator *op) { if (!gpsculpt_brush_init(C, op)) return OPERATOR_CANCELLED; - - RNA_BEGIN(op->ptr, itemptr, "stroke") + + RNA_BEGIN(op->ptr, itemptr, "stroke") { gpsculpt_brush_apply(C, op, &itemptr); } RNA_END; - + gpsculpt_brush_exit(C, op); - + return OPERATOR_FINISHED; } @@ -1594,13 +1594,13 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); bool needs_timer = false; float brush_rate = 0.0f; - + /* init painting data */ if (!gpsculpt_brush_init(C, op)) return OPERATOR_CANCELLED; - + gso = op->customdata; - + /* initialise type-specific data (used for the entire session) */ switch (gso->brush_type) { /* Brushes requiring timer... */ @@ -1608,7 +1608,7 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve brush_rate = 0.01f; // XXX: hardcoded needs_timer = true; break; - + case GP_EDITBRUSH_TYPE_STRENGTH: brush_rate = 0.01f; // XXX: hardcoded needs_timer = true; @@ -1618,39 +1618,39 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve brush_rate = 0.001f; // XXX: hardcoded needs_timer = true; break; - + case GP_EDITBRUSH_TYPE_TWIST: brush_rate = 0.01f; // XXX: hardcoded needs_timer = true; break; - + default: break; } - + /* register timer for increasing influence by hovering over an area */ if (needs_timer) { gso->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, brush_rate); } - + /* register modal handler */ WM_event_add_modal_handler(C, op); - + /* start drawing immediately? */ if (is_modal == false) { ARegion *ar = CTX_wm_region(C); - + /* ensure that we'll have a new frame to draw on */ gpsculpt_brush_init_stroke(gso); - + /* apply first dab... */ gso->is_painting = true; gpsculpt_brush_apply_event(C, op, event); - + /* redraw view with feedback */ ED_region_tag_redraw(ar); } - + return OPERATOR_RUNNING_MODAL; } @@ -1661,7 +1661,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); bool redraw_region = false; bool redraw_toolsettings = false; - + /* The operator can be in 2 states: Painting and Idling */ if (gso->is_painting) { /* Painting */ @@ -1671,11 +1671,11 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even case INBETWEEN_MOUSEMOVE: /* apply brush effect at new position */ gpsculpt_brush_apply_event(C, op, event); - + /* force redraw, so that the cursor will at least be valid */ redraw_region = true; break; - + /* Timer Tick - Only if this was our own timer */ case TIMER: if (event->customdata == gso->timer) { @@ -1684,7 +1684,7 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even gso->timerTick = false; } break; - + /* Adjust brush settings */ /* FIXME: Step increments and modifier keys are hardcoded here! */ case WHEELUPMOUSE: @@ -1699,12 +1699,12 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even gso->brush->size += 3; CLAMP_MAX(gso->brush->size, 300); } - + redraw_region = true; redraw_toolsettings = true; break; - - case WHEELDOWNMOUSE: + + case WHEELDOWNMOUSE: case PADMINUS: if (event->shift) { /* decrease strength */ @@ -1716,11 +1716,11 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even gso->brush->size -= 3; CLAMP_MIN(gso->brush->size, 1); } - + redraw_region = true; redraw_toolsettings = true; break; - + /* Painting mbut release = Stop painting (back to idle) */ case LEFTMOUSE: //BLI_assert(event->val == KM_RELEASE); @@ -1731,12 +1731,12 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even else { /* end sculpt session, since we're not modal */ gso->is_painting = false; - + gpsculpt_brush_exit(C, op); return OPERATOR_FINISHED; } break; - + /* Abort painting if any of the usual things are tried */ case MIDDLEMOUSE: case RIGHTMOUSE: @@ -1748,34 +1748,34 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even else { /* Idling */ BLI_assert(is_modal == true); - + switch (event->type) { /* Painting mbut press = Start painting (switch to painting state) */ case LEFTMOUSE: /* do initial "click" apply */ gso->is_painting = true; gso->first = true; - + gpsculpt_brush_init_stroke(gso); gpsculpt_brush_apply_event(C, op, event); break; - + /* Exit modal operator, based on the "standard" ops */ case RIGHTMOUSE: case ESCKEY: gpsculpt_brush_exit(C, op); return OPERATOR_FINISHED; - + /* MMB is often used for view manipulations */ case MIDDLEMOUSE: return OPERATOR_PASS_THROUGH; - + /* Mouse movements should update the brush cursor - Just redraw the active region */ case MOUSEMOVE: case INBETWEEN_MOUSEMOVE: redraw_region = true; break; - + /* Adjust brush settings */ /* FIXME: Step increments and modifier keys are hardcoded here! */ case WHEELUPMOUSE: @@ -1790,12 +1790,12 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even gso->brush->size += 3; CLAMP_MAX(gso->brush->size, 300); } - + redraw_region = true; redraw_toolsettings = true; break; - - case WHEELDOWNMOUSE: + + case WHEELDOWNMOUSE: case PADMINUS: if (event->shift) { /* decrease strength */ @@ -1807,41 +1807,41 @@ static int gpsculpt_brush_modal(bContext *C, wmOperator *op, const wmEvent *even gso->brush->size -= 3; CLAMP_MIN(gso->brush->size, 1); } - + redraw_region = true; redraw_toolsettings = true; break; - + /* Change Frame - Allowed */ case LEFTARROWKEY: case RIGHTARROWKEY: case UPARROWKEY: case DOWNARROWKEY: return OPERATOR_PASS_THROUGH; - + /* Camera/View Manipulations - Allowed */ /* (See rationale in gpencil_paint.c -> gpencil_draw_modal()) */ case PAD0: case PAD1: case PAD2: case PAD3: case PAD4: case PAD5: case PAD6: case PAD7: case PAD8: case PAD9: return OPERATOR_PASS_THROUGH; - + /* Unhandled event */ default: break; } } - + /* Redraw region? */ if (redraw_region) { ARegion *ar = CTX_wm_region(C); ED_region_tag_redraw(ar); } - + /* Redraw toolsettings (brush settings)? */ if (redraw_toolsettings) { WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); } - + return OPERATOR_RUNNING_MODAL; } @@ -1854,7 +1854,7 @@ void GPENCIL_OT_brush_paint(wmOperatorType *ot) ot->name = "Stroke Sculpt"; ot->idname = "GPENCIL_OT_brush_paint"; ot->description = "Apply tweaks to strokes by painting over the strokes"; // XXX - + /* api callbacks */ ot->exec = gpsculpt_brush_exec; ot->invoke = gpsculpt_brush_invoke; @@ -1869,7 +1869,7 @@ void GPENCIL_OT_brush_paint(wmOperatorType *ot) PropertyRNA *prop; prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Enter a mini 'sculpt-mode' if enabled, otherwise, exit after drawing a single stroke"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 7d455f214db..f44c3ee4113 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -174,7 +174,7 @@ static void gp_strokepoint_convertcoords( else { const float *fp = ED_view3d_cursor3d_get(scene, v3d); float mvalf[2]; - + /* get screen coordinate */ if (gps->flag & GP_STROKE_2DSPACE) { View2D *v2d = &ar->v2d; @@ -190,7 +190,7 @@ static void gp_strokepoint_convertcoords( mvalf[1] = (float)pt->y / 100.0f * ar->winy; } } - + ED_view3d_win_to_3d(v3d, ar, fp, mvalf, p3d); } } @@ -206,19 +206,19 @@ typedef struct tGpTimingData { bool realtime; /* Will overwrite end_frame in case of Original or CustomGap timing... */ float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ int seed; - + /* Data set from points, used to compute final timing FCurve */ int num_points, cur_point; - + /* Distances */ float *dists; float tot_dist; - + /* Times */ float *times; /* Note: Gap times will be negative! */ float tot_time, gap_tot_time; double inittime; - + /* Only used during creation of dists & times lists. */ float offset_time; } tGpTimingData; @@ -229,9 +229,9 @@ typedef struct tGpTimingData { static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) { float *tmp; - + BLI_assert(nbr > gtd->num_points); - + /* distances */ tmp = gtd->dists; gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); @@ -239,7 +239,7 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); MEM_freeN(tmp); } - + /* times */ tmp = gtd->times; gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); @@ -247,7 +247,7 @@ static void gp_timing_data_set_nbr(tGpTimingData *gtd, const int nbr) memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); MEM_freeN(tmp); } - + gtd->num_points = nbr; } @@ -257,7 +257,7 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_ini { float delta_time = 0.0f; const int cur_point = gtd->cur_point; - + if (!cur_point) { /* Special case, first point, if time is not 0.0f we have to compensate! */ gtd->offset_time = -time; @@ -267,18 +267,18 @@ static void gp_timing_data_add_point(tGpTimingData *gtd, const double stroke_ini /* This is a gap, negative value! */ gtd->times[cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time); delta_time = -gtd->times[cur_point] - gtd->times[cur_point - 1]; - + gtd->gap_tot_time += delta_time; } else { gtd->times[cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time + gtd->offset_time); delta_time = gtd->times[cur_point] - fabsf(gtd->times[cur_point - 1]); } - + gtd->tot_time += delta_time; gtd->tot_dist += delta_dist; gtd->dists[cur_point] = gtd->tot_dist; - + gtd->cur_point++; } @@ -293,7 +293,7 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx float *next_delta_time) { int j; - + for (j = idx + 1; j < gtd->num_points; j++) { if (gtd->times[j] < 0) { gtd->times[j] = -gtd->times[j]; @@ -312,16 +312,16 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx } else { float delta, min, max; - + /* This code ensures that if the first gaps have been shorter than average gap_duration, * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! */ delta = delta_time - (gtd->gap_duration * (*nbr_done_gaps)); - + /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ min = -gtd->gap_randomness - delta; CLAMP(min, -gtd->gap_randomness, 0.0f); - + /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ max = gtd->gap_randomness - delta; CLAMP(max, 0.0f, gtd->gap_randomness); @@ -336,7 +336,7 @@ static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, RNG *rng, const int idx break; } } - + return j - 1; } @@ -344,7 +344,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn { int i; float delta_time = 0.0f; - + for (i = 0; i < gtd->num_points; i++) { if (gtd->times[i] < 0 && i) { (*nbr_gaps)++; @@ -357,7 +357,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rn } } gtd->tot_time -= delta_time; - + *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; gtd->tot_time += *tot_gaps_time; if (G.debug & G_DEBUG) { @@ -374,18 +374,18 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR { /* Use actual recorded timing! */ const float time_start = (float)gtd->start_frame; - + float last_valid_time = 0.0f; int end_stroke_idx = -1, start_stroke_idx = 0; float end_stroke_time = 0.0f; - + /* CustomGaps specific */ float delta_time = 0.0f, next_delta_time = 0.0f; int nbr_done_gaps = 0; - + int i; float cfra; - + /* This is a bit tricky, as: * - We can't add arbitrarily close points on FCurve (in time). * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! @@ -401,11 +401,11 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR /* This one should *never* be negative! */ end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); } - + /* Simple proportional stuff... */ cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); - + /* And now, the checks about timing... */ if (i == start_stroke_idx) { /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and @@ -456,43 +456,43 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu PointerRNA ptr; PropertyRNA *prop = NULL; int nbr_gaps = 0, i; - + if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) return; - + /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ gtd->gap_duration = FRA2TIME(gtd->gap_duration); gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); - + /* Enable path! */ cu->flag |= CU_PATH; cu->pathlen = gtd->frame_range; - + /* Get RNA pointer to read/write path time values */ RNA_id_pointer_create((ID *)cu, &ptr); prop = RNA_struct_find_property(&ptr, "eval_time"); - + /* Ensure we have an F-Curve to add keyframes to */ act = verify_adt_action((ID *)cu, true); fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, true); - + if (G.debug & G_DEBUG) { printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); for (i = 0; i < gtd->num_points; i++) { printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); } } - + if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { float cfra; - + /* Linear extrapolation! */ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; - + cu->ctime = 0.0f; cfra = (float)gtd->start_frame; insert_keyframe_direct(reports, ptr, prop, fcu, cfra, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST); - + cu->ctime = cu->pathlen; if (gtd->realtime) { cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ @@ -506,35 +506,35 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu /* Use actual recorded timing! */ RNG *rng = BLI_rng_new(0); float time_range; - + /* CustomGaps specific */ float tot_gaps_time = 0.0f; - + /* Pre-process gaps, in case we don't want to keep their original timing */ if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { gp_stroke_path_animation_preprocess_gaps(gtd, rng, &nbr_gaps, &tot_gaps_time); } - + if (gtd->realtime) { time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ } else { time_range = (float)(gtd->end_frame - gtd->start_frame); } - + if (G.debug & G_DEBUG) { printf("GP Stroke Path Conversion: Starting keying!\n"); } - + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, rng, time_range, nbr_gaps, tot_gaps_time); - + BLI_rng_free(rng); } - + /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ calchandles_fcurve(fcu); - + if (G.debug & G_DEBUG) { printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); for (i = 0; i < gtd->num_points; i++) { @@ -542,9 +542,9 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu } printf("\n\n"); } - + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - + /* send updates */ DAG_id_tag_update(&cu->id, 0); } @@ -564,7 +564,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl { copy_v3_v3(bp->vec, p); bp->vec[3] = 1.0f; - + /* set settings */ bp->f1 = SELECT; bp->radius = width * rad_fac; @@ -576,7 +576,7 @@ static void gp_stroke_to_path_add_point(tGpTimingData *gtd, BPoint *bp, const fl else if (bp->weight > minmax_weights[1]) { minmax_weights[1] = bp->weight; } - + /* Update timing data */ if (do_gtd) { gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); @@ -593,7 +593,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0); int i, old_nbp = 0; - + /* create new 'nurb' or extend current one within the curve */ if (nu) { old_nbp = nu->pntsu; @@ -605,7 +605,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv } else { nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); - + nu->pntsu = gps->totpoints + add_start_end_points; nu->pntsv = 1; nu->orderu = 2; /* point-to-point! */ @@ -614,16 +614,16 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv nu->resolu = cu->resolu; nu->resolv = cu->resolv; nu->knotsu = NULL; - + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); - + stitch = false; /* Security! */ } - + if (do_gtd) { gp_timing_data_set_nbr(gtd, nu->pntsu); } - + /* If needed, make the link between both strokes with two zero-radius additional points */ /* About "zero-radius" point interpolations: * - If we have at least two points in current curve (most common case), we linearly extrapolate @@ -636,16 +636,16 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv if (curnu && !stitch && old_nbp) { float p1[3], p2[3], p[3], next_p[3]; float dt1 = 0.0f, dt2 = 0.0f; - + BLI_assert(gps->prev != NULL); - + prev_bp = NULL; if ((old_nbp > 1) && (gps->prev->totpoints > 1)) { /* Only use last curve segment if previous stroke was not a single-point one! */ prev_bp = &nu->bp[old_nbp - 2]; } bp = &nu->bp[old_nbp - 1]; - + /* First point */ gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); if (prev_bp) { @@ -664,7 +664,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv bp++; gp_stroke_to_path_add_point(gtd, bp, p1, (bp - 1)->vec, do_gtd, gps->prev->inittime, dt1, 0.0f, rad_fac, minmax_weights); - + /* Second point */ /* Note dt2 is always negative, which marks the gap. */ if (gps->totpoints > 1) { @@ -682,13 +682,13 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv } bp++; gp_stroke_to_path_add_point(gtd, bp, p2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights); - + old_nbp += 2; } else if (add_start_point) { float p[3], next_p[3]; float dt = 0.0f; - + gp_strokepoint_convertcoords(C, gpl, gps, gps->points, p, subrect); if (gps->totpoints > 1) { gp_strokepoint_convertcoords(C, gpl, gps, gps->points + 1, next_p, subrect); @@ -706,14 +706,14 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv * would not work (it would be *before* gtd->inittime, which is not supported currently). */ gp_stroke_to_path_add_point(gtd, bp, p, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); - + old_nbp++; } - + if (old_nbp) { prev_bp = &nu->bp[old_nbp - 1]; } - + /* add points */ for (i = (stitch) ? 1 : 0, pt = &gps->points[(stitch) ? 1 : 0], bp = &nu->bp[old_nbp]; i < gps->totpoints; @@ -721,20 +721,20 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv { float p[3]; float width = pt->pressure * (gps->thickness + gpl->thickness) * WIDTH_CORR_FAC; - + /* get coordinates to add at */ gp_strokepoint_convertcoords(C, gpl, gps, pt, p, subrect); - + gp_stroke_to_path_add_point(gtd, bp, p, (prev_bp) ? prev_bp->vec : p, do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights); - + prev_bp = bp; } if (add_end_point) { float p[3]; float dt = 0.0f; - + if (gps->totpoints > 1) { interp_v3_v3v3(p, prev_bp->vec, (prev_bp - 1)->vec, -GAP_DFAC); if (do_gtd) { @@ -750,7 +750,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv /* Note bp has already been incremented in main loop above, so it points to the right place. */ gp_stroke_to_path_add_point(gtd, bp, p, prev_bp->vec, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); } - + /* add nurb to curve */ if (!curnu || !*curnu) { BLI_addtail(&cu->nurb, nu); @@ -758,7 +758,7 @@ static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curv if (curnu) { *curnu = nu; } - + BKE_nurb_knot_calc_u(nu); } @@ -773,7 +773,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt, copy_v3_v3(bezt->vec[0], h1); copy_v3_v3(bezt->vec[1], p); copy_v3_v3(bezt->vec[2], h2); - + /* set settings */ bezt->h1 = bezt->h2 = HD_FREE; bezt->f1 = bezt->f2 = bezt->f3 = SELECT; @@ -786,7 +786,7 @@ static void gp_stroke_to_bezier_add_point(tGpTimingData *gtd, BezTriple *bezt, else if (bezt->weight > minmax_weights[1]) { minmax_weights[1] = bezt->weight; } - + /* Update timing data */ if (do_gtd) { gp_timing_data_add_point(gtd, inittime, time, len_v3v3(prev_p, p)); @@ -804,7 +804,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu const int add_start_end_points = (add_start_point ? 1 : 0) + (add_end_point ? 1 : 0); float p3d_cur[3], p3d_prev[3], p3d_next[3], h1[3], h2[3]; const bool do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); - + /* create new 'nurb' or extend current one within the curve */ if (nu) { old_nbezt = nu->pntsu; @@ -816,22 +816,22 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu } else { nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - + nu->pntsu = gps->totpoints + add_start_end_points; nu->resolu = 12; nu->resolv = 12; nu->type = CU_BEZIER; nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * nu->pntsu, "bezts"); - + stitch = false; /* Security! */ } - + if (do_gtd) { gp_timing_data_set_nbr(gtd, nu->pntsu); } - + tot = gps->totpoints; - + /* get initial coordinates */ pt = gps->points; if (tot) { @@ -843,11 +843,11 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); } } - + /* If needed, make the link between both strokes with two zero-radius additional points */ if (curnu && old_nbezt) { BLI_assert(gps->prev != NULL); - + /* Update last point's second handle */ if (stitch) { bezt = &nu->bezt[old_nbezt - 1]; @@ -855,7 +855,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu copy_v3_v3(bezt->vec[2], h2); pt++; } - + /* Create "link points" */ /* About "zero-radius" point interpolations: * - If we have at least two points in current curve (most common case), we linearly extrapolate @@ -868,14 +868,14 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu else { float p1[3], p2[3]; float dt1 = 0.0f, dt2 = 0.0f; - + prev_bezt = NULL; if ((old_nbezt > 1) && (gps->prev->totpoints > 1)) { /* Only use last curve segment if previous stroke was not a single-point one! */ prev_bezt = &nu->bezt[old_nbezt - 2]; } bezt = &nu->bezt[old_nbezt - 1]; - + /* First point */ if (prev_bezt) { interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); @@ -890,7 +890,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu dt1 = interpf(gps->inittime - gps->prev->inittime, 0.0f, GAP_DFAC); } } - + /* Second point */ /* Note dt2 is always negative, which marks the gap. */ if (tot > 1) { @@ -905,25 +905,25 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu dt2 = interpf(gps->prev->inittime - gps->inittime, 0.0f, GAP_DFAC); } } - + /* Second handle of last point of previous stroke. */ interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); copy_v3_v3(bezt->vec[2], h2); - + /* First point */ interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); bezt++; gp_stroke_to_bezier_add_point(gtd, bezt, p1, h1, h2, (bezt - 1)->vec[1], do_gtd, gps->prev->inittime, dt1, 0.0f, rad_fac, minmax_weights); - + /* Second point */ interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); bezt++; gp_stroke_to_bezier_add_point(gtd, bezt, p2, h1, h2, p1, do_gtd, gps->inittime, dt2, 0.0f, rad_fac, minmax_weights); - + old_nbezt += 2; copy_v3_v3(p3d_prev, p2); } @@ -931,7 +931,7 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu else if (add_start_point) { float p[3]; float dt = 0.0f; - + if (gps->totpoints > 1) { interp_v3_v3v3(p, p3d_cur, p3d_next, -GAP_DFAC); if (do_gtd) { @@ -948,51 +948,51 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu bezt = &nu->bezt[old_nbezt]; gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, p, do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); - + old_nbezt++; copy_v3_v3(p3d_prev, p); } - + if (old_nbezt) { prev_bezt = &nu->bezt[old_nbezt - 1]; } - + /* add points */ for (i = stitch ? 1 : 0, bezt = &nu->bezt[old_nbezt]; i < tot; i++, pt++, bezt++) { float width = pt->pressure * (gps->thickness + gpl->thickness) * WIDTH_CORR_FAC; - + if (i || old_nbezt) { interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); } else { interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); } - + if (i < tot - 1) { interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); } else { interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); } - + gp_stroke_to_bezier_add_point(gtd, bezt, p3d_cur, h1, h2, prev_bezt ? prev_bezt->vec[1] : p3d_cur, do_gtd, gps->inittime, pt->time, width, rad_fac, minmax_weights); - + /* shift coord vects */ copy_v3_v3(p3d_prev, p3d_cur); copy_v3_v3(p3d_cur, p3d_next); - + if (i + 2 < tot) { gp_strokepoint_convertcoords(C, gpl, gps, pt + 2, p3d_next, subrect); } - + prev_bezt = bezt; } if (add_end_point) { float p[3]; float dt = 0.0f; - + if (gps->totpoints > 1) { interp_v3_v3v3(p, prev_bezt->vec[1], (prev_bezt - 1)->vec[1], -GAP_DFAC); if (do_gtd) { @@ -1005,11 +1005,11 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu p[0] += GAP_DFAC; /* Rather arbitrary... */ dt = GAP_DFAC; /* Rather arbitrary too! */ } - + /* Second handle of last point of this stroke. */ interp_v3_v3v3(h2, prev_bezt->vec[1], p, BEZT_HANDLE_FAC); copy_v3_v3(prev_bezt->vec[2], h2); - + /* The end point */ interp_v3_v3v3(h1, p, prev_bezt->vec[1], BEZT_HANDLE_FAC); interp_v3_v3v3(h2, p, prev_bezt->vec[1], -BEZT_HANDLE_FAC); @@ -1017,10 +1017,10 @@ static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Cu gp_stroke_to_bezier_add_point(gtd, bezt, p, h1, h2, prev_bezt->vec[1], do_gtd, gps->inittime, dt, 0.0f, rad_fac, minmax_weights); } - + /* must calculate handles or else we crash */ BKE_nurb_handles_calc(nu); - + if (!curnu || !*curnu) { BLI_addtail(&cu->nurb, nu); } @@ -1050,7 +1050,7 @@ static void gp_stroke_finalize_curve_endpoints(Curve *cu) bp[i].weight = bp[i].radius = 0.0f; } } - + /* end */ nu = cu->nurb.last; i = nu->pntsu - 1; @@ -1074,13 +1074,13 @@ static void gp_stroke_norm_curve_weights(Curve *cu, const float minmax_weights[2 const float delta = minmax_weights[0]; float fac; int i; - + /* when delta == minmax_weights[0] == minmax_weights[1], we get div by zero [#35686] */ if (IS_EQF(delta, minmax_weights[1])) fac = 1.0f; else fac = 1.0f / (minmax_weights[1] - delta); - + for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->bezt) { BezTriple *bezt = nu->bezt; @@ -1101,10 +1101,10 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) { View3D *v3d = CTX_wm_view3d(C); ARegion *ar = CTX_wm_region(C); - + if (v3d) { RegionView3D *rv3d = ar->regiondata; - + /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { Scene *scene = CTX_data_scene(C); @@ -1112,7 +1112,7 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) return 1; } } - + return 0; } @@ -1130,55 +1130,55 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG Nurb *nu = NULL; Base *base_orig = BASACT, *base_new = NULL; float minmax_weights[2] = {1.0f, 0.0f}; - + /* camera framing */ rctf subrect, *subrect_ptr = NULL; - + /* error checking */ if (ELEM(NULL, gpd, gpl, gpf)) return; - + /* only convert if there are any strokes on this layer's frame to convert */ if (BLI_listbase_is_empty(&gpf->strokes)) return; - + /* initialize camera framing */ if (gp_camera_view_subrect(C, &subrect)) { subrect_ptr = &subrect; } - + /* init the curve object (remove rotation and get curve data from it) * - must clear transforms set on object, as those skew our results */ ob = BKE_object_add_only_object(bmain, OB_CURVE, gpl->info); cu = ob->data = BKE_curve_add(bmain, gpl->info, OB_CURVE); base_new = BKE_scene_base_add(scene, ob); - + cu->flag |= CU_3D; - + gtd->inittime = ((bGPDstroke *)gpf->strokes.first)->inittime; - + /* add points to curve */ for (gps = gpf->strokes.first; gps; gps = gps->next) { const bool add_start_point = (link_strokes && !(prev_gps)); const bool add_end_point = (link_strokes && !(gps->next)); - + /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, and stitch them to previous one. */ bool stitch = false; if (prev_gps) { bGPDspoint *pt1 = &prev_gps->points[prev_gps->totpoints - 1]; bGPDspoint *pt2 = &gps->points[0]; - + if ((pt1->x == pt2->x) && (pt1->y == pt2->y)) { stitch = true; } } - + /* Decide whether we connect this stroke to previous one */ if (!(stitch || link_strokes)) { nu = NULL; } - + switch (mode) { case GP_STROKECONVERT_PATH: gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, @@ -1195,26 +1195,26 @@ static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bG } prev_gps = gps; } - + /* If link_strokes, be sure first and last points have a zero weight/size! */ if (link_strokes) { gp_stroke_finalize_curve_endpoints(cu); } - + /* Update curve's weights, if needed */ if (norm_weights && ((minmax_weights[0] > 0.0f) || (minmax_weights[1] < 1.0f))) { gp_stroke_norm_curve_weights(cu, minmax_weights); } - + /* Create the path animation, if needed */ gp_stroke_path_animation(C, reports, cu, gtd); - + if (mode == GP_STROKECONVERT_POLY) { for (nu = cu->nurb.first; nu; nu = nu->next) { BKE_nurb_type_convert(nu, CU_POLY, false); } } - + /* set the layer and select */ base_new->lay = ob->lay = base_orig ? base_orig->lay : BKE_screen_view3d_layer_active(v3d, scene); base_new->flag = ob->flag = base_new->flag | SELECT; @@ -1234,17 +1234,17 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe double base_time, cur_time, prev_time = -1.0; int i; bool valid = true; - + if (!gpl || !(gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0)) || !(gps = gpf->strokes.first)) return false; - + do { base_time = cur_time = gps->inittime; if (cur_time <= prev_time) { valid = false; break; } - + prev_time = cur_time; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { cur_time = base_time + (double)pt->time; @@ -1257,12 +1257,12 @@ static bool gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOpe } prev_time = cur_time; } - + if (!valid) { break; } } while ((gps = gps->next)); - + if (op) { RNA_boolean_set(op->ptr, "use_timing_data", valid); } @@ -1274,7 +1274,7 @@ static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UN { int start_frame = RNA_int_get(ptr, "start_frame"); int end_frame = RNA_int_get(ptr, "end_frame"); - + if (end_frame <= start_frame) { RNA_int_set(ptr, "end_frame", start_frame + 1); } @@ -1287,7 +1287,7 @@ static int gp_convert_poll(bContext *C) bGPDframe *gpf = NULL; ScrArea *sa = CTX_wm_area(C); Scene *scene = CTX_data_scene(C); - + /* only if the current view is 3D View, if there's valid data (i.e. at least one stroke!), * and if we are not in edit mode! */ @@ -1310,19 +1310,19 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) const bool link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); bool valid_timing; tGpTimingData gtd; - + /* check if there's data to work with */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data to work on"); return OPERATOR_CANCELLED; } - + if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { BKE_report(op->reports, RPT_WARNING, "Current Grease Pencil strokes have no valid timing data, most timing options will be hidden!"); } valid_timing = RNA_property_boolean_get(op->ptr, prop); - + gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); /* Check for illegal timing mode! */ if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { @@ -1332,7 +1332,7 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) if (!link_strokes) { gtd.mode = GP_STROKECONVERT_TIMING_NONE; } - + /* grab all relevant settings */ gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); @@ -1347,10 +1347,10 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; gtd.inittime = 0.0; gtd.offset_time = 0.0f; - + /* perform conversion */ gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); - + /* free temp memory */ if (gtd.dists) { MEM_freeN(gtd.dists); @@ -1360,11 +1360,11 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) MEM_freeN(gtd.times); gtd.times = NULL; } - + /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - + /* done */ return OPERATOR_FINISHED; } @@ -1378,7 +1378,7 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) float gap_duration = RNA_float_get(ptr, "gap_duration"); float gap_randomness = RNA_float_get(ptr, "gap_randomness"); const bool valid_timing = RNA_boolean_get(ptr, "use_timing_data"); - + /* Always show those props */ if (STREQ(prop_id, "type") || STREQ(prop_id, "use_normalize_weights") || @@ -1387,16 +1387,16 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) { return true; } - + /* Never show this prop */ if (STREQ(prop_id, "use_timing_data")) return false; - + if (link_strokes) { /* Only show when link_stroke is true */ if (STREQ(prop_id, "timing_mode")) return true; - + if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { /* Only show when link_stroke is true and stroke timing is enabled */ if (STREQ(prop_id, "frame_range") || @@ -1404,31 +1404,31 @@ static bool gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) { return true; } - + /* Only show if we have valid timing data! */ if (valid_timing && STREQ(prop_id, "use_realtime")) return true; - + /* Only show if realtime or valid_timing is false! */ if ((!realtime || !valid_timing) && STREQ(prop_id, "end_frame")) return true; - + if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { /* Only show for custom gaps! */ if (STREQ(prop_id, "gap_duration")) return true; - + /* Only show randomness for non-null custom gaps! */ if (STREQ(prop_id, "gap_randomness") && (gap_duration > 0.0f)) return true; - + /* Only show seed for randomize action! */ if (STREQ(prop_id, "seed") && (gap_duration > 0.0f) && (gap_randomness > 0.0f)) return true; } } } - + /* Else, hidden! */ return false; } @@ -1438,9 +1438,9 @@ static void gp_convert_ui(bContext *C, wmOperator *op) uiLayout *layout = op->layout; wmWindowManager *wm = CTX_wm_manager(C); PointerRNA ptr; - + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - + /* Main auto-draw call */ uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); } @@ -1448,35 +1448,35 @@ static void gp_convert_ui(bContext *C, wmOperator *op) void GPENCIL_OT_convert(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Convert Grease Pencil"; ot->idname = "GPENCIL_OT_convert"; ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; - + /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_convert_layer_exec; ot->poll = gp_convert_poll; ot->ui = gp_convert_ui; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); - + RNA_def_boolean(ot->srna, "use_normalize_weights", true, "Normalize Weight", "Normalize weight (set from stroke width)"); RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); RNA_def_boolean(ot->srna, "use_link_strokes", true, "Link Strokes", "Whether to link strokes with zero-radius sections of curves"); - + prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, "Timing Mode", "How to use timing data stored in strokes"); RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); - + RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", "The duration of evaluation of the path control curve", 1, 1000); RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", @@ -1486,7 +1486,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", "The end frame of the path control curve (if Realtime is not set)", 1, 100000); RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); - + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", "Custom Gap mode: (Average) length of gaps, in frames " "(Note: Realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); @@ -1494,7 +1494,7 @@ void GPENCIL_OT_convert(wmOperatorType *ot) "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", "Custom Gap mode: Random generator seed", 0, 100); - + /* Note: Internal use, this one will always be hidden by UI code... */ prop = RNA_def_boolean(ot->srna, "use_timing_data", false, "Has Valid Timing", "Whether the converted Grease Pencil layer has valid timing data (internal use)"); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index 9d183222c2d..2e8e48b2f15 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -93,7 +93,7 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) else { /* decrement user count and add new datablock */ bGPdata *gpd = (*gpd_ptr); - + id_us_min(&gpd->id); *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); @@ -106,10 +106,10 @@ static int gp_data_add_exec(bContext *C, wmOperator *op) } } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -120,7 +120,7 @@ void GPENCIL_OT_data_add(wmOperatorType *ot) ot->idname = "GPENCIL_OT_data_add"; ot->description = "Add new Grease Pencil data-block"; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_data_add_exec; ot->poll = gp_add_poll; @@ -132,7 +132,7 @@ void GPENCIL_OT_data_add(wmOperatorType *ot) static int gp_data_unlink_poll(bContext *C) { bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - + /* if we have access to some active data, make sure there's a datablock before enabling this */ return (gpd_ptr && *gpd_ptr); } @@ -142,7 +142,7 @@ static int gp_data_unlink_poll(bContext *C) static int gp_data_unlink_exec(bContext *C, wmOperator *op) { bGPdata **gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - + if (gpd_ptr == NULL) { BKE_report(op->reports, RPT_ERROR, "Nowhere for grease pencil data to go"); return OPERATOR_CANCELLED; @@ -154,10 +154,10 @@ static int gp_data_unlink_exec(bContext *C, wmOperator *op) id_us_min(&gpd->id); *gpd_ptr = NULL; } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -168,7 +168,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot) ot->idname = "GPENCIL_OT_data_unlink"; ot->description = "Unlink active Grease Pencil data-block"; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_data_unlink_exec; ot->poll = gp_data_unlink_poll; @@ -193,7 +193,7 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) } if (*gpd_ptr == NULL) *gpd_ptr = BKE_gpencil_data_addnew(DATA_("GPencil")); - + /* if not exist brushes, create a new set */ if (ts) { if (BLI_listbase_is_empty(&ts->gp_brushes)) { @@ -204,10 +204,10 @@ static int gp_layer_add_exec(bContext *C, wmOperator *op) /* add new layer now */ BKE_gpencil_layer_addnew(*gpd_ptr, DATA_("GP_Layer"), true); - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -217,9 +217,9 @@ void GPENCIL_OT_layer_add(wmOperatorType *ot) ot->name = "Add New Layer"; ot->idname = "GPENCIL_OT_layer_add"; ot->description = "Add new Grease Pencil layer for the active Grease Pencil data-block"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_layer_add_exec; ot->poll = gp_add_poll; @@ -231,16 +231,16 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + /* sanity checks */ if (ELEM(NULL, gpd, gpl)) return OPERATOR_CANCELLED; - + if (gpl->flag & GP_LAYER_LOCKED) { BKE_report(op->reports, RPT_ERROR, "Cannot delete locked layers"); return OPERATOR_CANCELLED; } - + /* make the layer before this the new active layer * - use the one after if this is the first * - if this is the only layer, this naturally becomes NULL @@ -249,13 +249,13 @@ static int gp_layer_remove_exec(bContext *C, wmOperator *op) BKE_gpencil_layer_setactive(gpd, gpl->prev); else BKE_gpencil_layer_setactive(gpd, gpl->next); - + /* delete the layer now... */ BKE_gpencil_layer_delete(gpd, gpl); - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -265,9 +265,9 @@ void GPENCIL_OT_layer_remove(wmOperatorType *ot) ot->name = "Remove Layer"; ot->idname = "GPENCIL_OT_layer_remove"; ot->description = "Remove active Grease Pencil layer"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_layer_remove_exec; ot->poll = gp_active_layer_poll; @@ -284,18 +284,18 @@ static int gp_layer_move_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + int direction = RNA_enum_get(op->ptr, "type"); - + /* sanity checks */ if (ELEM(NULL, gpd, gpl)) return OPERATOR_CANCELLED; - + BLI_assert(ELEM(direction, -1, 0, 1)); /* we use value below */ if (BLI_listbase_link_move(&gpd->layers, gpl, direction)) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } - + return OPERATOR_FINISHED; } @@ -306,19 +306,19 @@ void GPENCIL_OT_layer_move(wmOperatorType *ot) {GP_LAYER_MOVE_DOWN, "DOWN", 0, "Down", ""}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Move Grease Pencil Layer"; ot->idname = "GPENCIL_OT_layer_move"; ot->description = "Move the active Grease Pencil layer up/down in the list"; - + /* api callbacks */ ot->exec = gp_layer_move_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); } @@ -329,22 +329,22 @@ static int gp_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); bGPDlayer *new_layer; - + /* sanity checks */ if (ELEM(NULL, gpd, gpl)) return OPERATOR_CANCELLED; - + /* make copy of layer, and add it immediately after the existing layer */ new_layer = BKE_gpencil_layer_duplicate(gpl); BLI_insertlinkafter(&gpd->layers, gpl, new_layer); - + /* ensure new layer has a unique name, and is now the active layer */ BLI_uniquename(&gpd->layers, new_layer, DATA_("GP_Layer"), '.', offsetof(bGPDlayer, info), sizeof(new_layer->info)); BKE_gpencil_layer_setactive(gpd, new_layer); - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -354,11 +354,11 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) ot->name = "Duplicate Layer"; ot->idname = "GPENCIL_OT_layer_duplicate"; ot->description = "Make a copy of the active Grease Pencil layer"; - + /* callbacks */ ot->exec = gp_layer_copy_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -370,14 +370,14 @@ static int gp_hide_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd); bool unselected = RNA_boolean_get(op->ptr, "unselected"); - + /* sanity checks */ if (ELEM(NULL, gpd, layer)) return OPERATOR_CANCELLED; - + if (unselected) { bGPDlayer *gpl; - + /* hide unselected */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl != layer) { @@ -389,10 +389,10 @@ static int gp_hide_exec(bContext *C, wmOperator *op) /* hide selected/active */ layer->flag |= GP_LAYER_HIDE; } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -402,14 +402,14 @@ void GPENCIL_OT_hide(wmOperatorType *ot) ot->name = "Hide Layer(s)"; ot->idname = "GPENCIL_OT_hide"; ot->description = "Hide selected/unselected Grease Pencil layers"; - + /* callbacks */ ot->exec = gp_hide_exec; ot->poll = gp_active_layer_poll; /* NOTE: we need an active layer to play with */ - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected layers"); } @@ -452,7 +452,7 @@ static int gp_reveal_exec(bContext *C, wmOperator *op) /* sanity checks */ if (gpd == NULL) return OPERATOR_CANCELLED; - + for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl->flag & GP_LAYER_HIDE) { @@ -476,10 +476,10 @@ static int gp_reveal_exec(bContext *C, wmOperator *op) } } } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -489,11 +489,11 @@ void GPENCIL_OT_reveal(wmOperatorType *ot) ot->name = "Show All Layers"; ot->idname = "GPENCIL_OT_reveal"; ot->description = "Show all Grease Pencil layers"; - + /* callbacks */ ot->exec = gp_reveal_exec; ot->poll = gp_reveal_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -507,19 +507,19 @@ static int gp_lock_all_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl; - + /* sanity checks */ if (gpd == NULL) return OPERATOR_CANCELLED; - + /* make all layers non-editable */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { gpl->flag |= GP_LAYER_LOCKED; } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -529,11 +529,11 @@ void GPENCIL_OT_lock_all(wmOperatorType *ot) ot->name = "Lock All Layers"; ot->idname = "GPENCIL_OT_lock_all"; ot->description = "Lock all Grease Pencil layers to prevent them from being accidentally modified"; - + /* callbacks */ ot->exec = gp_lock_all_exec; ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */ - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -544,19 +544,19 @@ static int gp_unlock_all_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl; - + /* sanity checks */ if (gpd == NULL) return OPERATOR_CANCELLED; - + /* make all layers editable again */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { gpl->flag &= ~GP_LAYER_LOCKED; } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -566,11 +566,11 @@ void GPENCIL_OT_unlock_all(wmOperatorType *ot) ot->name = "Unlock All Layers"; ot->idname = "GPENCIL_OT_unlock_all"; ot->description = "Unlock all Grease Pencil layers so that they can be edited"; - + /* callbacks */ ot->exec = gp_unlock_all_exec; ot->poll = gp_reveal_poll; /* XXX: could use dedicated poll later */ - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -584,21 +584,21 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op) bGPDlayer *gpl; int flags = GP_LAYER_LOCKED; bool isolate = false; - + if (RNA_boolean_get(op->ptr, "affect_visibility")) flags |= GP_LAYER_HIDE; - + if (ELEM(NULL, gpd, layer)) { BKE_report(op->reports, RPT_ERROR, "No active layer to isolate"); return OPERATOR_CANCELLED; } - + /* Test whether to isolate or clear all flags */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* Skip if this is the active layer */ if (gpl == layer) continue; - + /* If the flags aren't set, that means that the layer is * not alone, so we have some layers to isolate still */ @@ -607,7 +607,7 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op) break; } } - + /* Set/Clear flags as appropriate */ /* TODO: Include onionskinning on this list? */ if (isolate) { @@ -625,10 +625,10 @@ static int gp_isolate_layer_exec(bContext *C, wmOperator *op) gpl->flag &= ~flags; } } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -638,14 +638,14 @@ void GPENCIL_OT_layer_isolate(wmOperatorType *ot) ot->name = "Isolate Layer"; ot->idname = "GPENCIL_OT_layer_isolate"; ot->description = "Toggle whether the active layer is the only one that can be edited and/or visible"; - + /* callbacks */ ot->exec = gp_isolate_layer_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ RNA_def_boolean(ot->srna, "affect_visibility", false, "Affect Visibility", "In addition to toggling the editability, also affect the visibility"); @@ -712,13 +712,13 @@ static int gp_layer_change_invoke(bContext *C, wmOperator *op, const wmEvent *UN { uiPopupMenu *pup; uiLayout *layout; - + /* call the menu, which will call this operator again, hence the canceled */ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE); layout = UI_popup_menu_layout(pup); uiItemsEnumO(layout, "GPENCIL_OT_layer_change", "layer"); UI_popup_menu_end(C, pup); - + return OPERATOR_INTERFACE; } @@ -727,7 +727,7 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op) bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *gpl = NULL; int layer_num = RNA_enum_get(op->ptr, "layer"); - + /* Get layer or create new one */ if (layer_num == -1) { /* Create layer */ @@ -736,19 +736,19 @@ static int gp_layer_change_exec(bContext *C, wmOperator *op) else { /* Try to get layer */ gpl = BLI_findlink(&gpd->layers, layer_num); - + if (gpl == NULL) { BKE_reportf(op->reports, RPT_ERROR, "Cannot change to non-existent layer (index = %d)", layer_num); return OPERATOR_CANCELLED; } } - + /* Set active layer */ BKE_gpencil_layer_setactive(gpd, gpl); - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -758,15 +758,15 @@ void GPENCIL_OT_layer_change(wmOperatorType *ot) ot->name = "Change Layer"; ot->idname = "GPENCIL_OT_layer_change"; ot->description = "Change active Grease Pencil layer"; - + /* callbacks */ ot->invoke = gp_layer_change_invoke; ot->exec = gp_layer_change_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* gp layer to use (dynamic enum) */ ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", ""); RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index bc54bd89958..d48efd75746 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -91,10 +91,10 @@ static int gpencil_editmode_toggle_poll(bContext *C) static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + if (gpd == NULL) return OPERATOR_CANCELLED; - + /* Just toggle editmode flag... */ gpd->flag ^= GP_DATA_STROKE_EDITMODE; /* recalculate parent matrix */ @@ -105,7 +105,7 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); WM_event_add_notifier(C, NC_GPENCIL | ND_GPENCIL_EDITMODE, NULL); WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL); - + return OPERATOR_FINISHED; } @@ -115,11 +115,11 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot) ot->name = "Strokes Edit Mode Toggle"; ot->idname = "GPENCIL_OT_editmode_toggle"; ot->description = "Enter/Exit edit mode for Grease Pencil strokes"; - + /* callbacks */ ot->exec = gpencil_editmode_toggle_exec; ot->poll = gpencil_editmode_toggle_poll; - + /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; } @@ -180,10 +180,10 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co { bGPDspoint *pt; int i; - + int start_idx = -1; - - + + /* Step through the original stroke's points: * - We accumulate selected points (from start_idx to current index) * and then convert that to a new stroke @@ -198,7 +198,7 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co } else { size_t len = 0; - + /* is this the end of current island yet? * 1) Point i-1 was the last one that was selected * 2) Point i is the last in the array @@ -210,29 +210,29 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co len = i - start_idx + 1; } //printf("copying from %d to %d = %d\n", start_idx, i, len); - + /* make copies of the relevant data */ if (len) { bGPDstroke *gpsd; - + /* make a stupid copy first of the entire stroke (to get the flags too) */ gpsd = MEM_dupallocN(gps); BLI_strncpy(gpsd->tmp_layerinfo, layername, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */ - + /* initialize triangle memory - will be calculated on next redraw */ gpsd->triangles = NULL; gpsd->flag |= GP_STROKE_RECALC_CACHES; gpsd->tot_triangles = 0; - + /* now, make a new points array, and copy of the relevant parts */ gpsd->points = MEM_callocN(sizeof(bGPDspoint) * len, "gps stroke points copy"); memcpy(gpsd->points, gps->points + start_idx, sizeof(bGPDspoint) * len); gpsd->totpoints = len; - + /* add to temp buffer */ gpsd->next = gpsd->prev = NULL; BLI_addtail(new_strokes, gpsd); - + /* cleanup + reset for next */ start_idx = -1; } @@ -243,12 +243,12 @@ static void gp_duplicate_points(const bGPDstroke *gps, ListBase *new_strokes, co static int gp_duplicate_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); return OPERATOR_CANCELLED; } - + /* for each visible (and editable) layer's selected strokes, * copy the strokes into a temporary buffer, then append * once all done @@ -258,22 +258,22 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) ListBase new_strokes = {NULL, NULL}; bGPDframe *gpf = gpl->actframe; bGPDstroke *gps; - + if (gpf == NULL) continue; - + /* make copies of selected strokes, and deselect these once we're done */ for (gps = gpf->strokes.first; gps; gps = gps->next) { /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - + if (gps->flag & GP_STROKE_SELECT) { if (gps->totpoints == 1) { /* Special Case: If there's just a single point in this stroke... */ bGPDstroke *gpsd; - + /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); @@ -282,7 +282,7 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) /* triangle information - will be calculated on next redraw */ gpsd->flag |= GP_STROKE_RECALC_CACHES; gpsd->triangles = NULL; - + /* add to temp buffer */ gpsd->next = gpsd->prev = NULL; BLI_addtail(&new_strokes, gpsd); @@ -291,23 +291,23 @@ static int gp_duplicate_exec(bContext *C, wmOperator *op) /* delegate to a helper, as there's too much to fit in here (for copying subsets)... */ gp_duplicate_points(gps, &new_strokes, gpl->info); } - + /* deselect original stroke, or else the originals get moved too * (when using the copy + move macro) */ gps->flag &= ~GP_STROKE_SELECT; } } - + /* add all new strokes in temp buffer to the frame (preventing double-copies) */ BLI_movelisttolist(&gpf->strokes, &new_strokes); BLI_assert(new_strokes.first == NULL); } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -317,11 +317,11 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) ot->name = "Duplicate Strokes"; ot->idname = "GPENCIL_OT_duplicate"; ot->description = "Duplicate the selected Grease Pencil strokes"; - + /* callbacks */ ot->exec = gp_duplicate_exec; ot->poll = gp_stroke_edit_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -350,7 +350,7 @@ static GHash *gp_strokes_copypastebuf_colors = NULL; void ED_gpencil_strokes_copybuf_free(void) { bGPDstroke *gps, *gpsn; - + /* Free the palettes buffer * NOTE: This is done before the strokes so that the name ptrs (keys) are still safe */ @@ -358,17 +358,17 @@ void ED_gpencil_strokes_copybuf_free(void) BLI_ghash_free(gp_strokes_copypastebuf_colors, NULL, MEM_freeN); gp_strokes_copypastebuf_colors = NULL; } - + /* Free the stroke buffer */ for (gps = gp_strokes_copypastebuf.first; gps; gps = gpsn) { gpsn = gps->next; - + if (gps->points) MEM_freeN(gps->points); if (gps->triangles) MEM_freeN(gps->triangles); - + BLI_freelinkN(&gp_strokes_copypastebuf, gps); } - + gp_strokes_copypastebuf.first = gp_strokes_copypastebuf.last = NULL; } @@ -379,18 +379,18 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd) { GHash *new_colors = BLI_ghash_str_new("GPencil Paste Dst Colors"); GHashIterator gh_iter; - + /* If there's no active palette yet (i.e. new datablock), add one */ bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); if (palette == NULL) { palette = BKE_gpencil_palette_addnew(gpd, "Pasted Palette", true); } - + /* For each color, figure out what to map to... */ GHASH_ITER(gh_iter, gp_strokes_copypastebuf_colors) { bGPDpalettecolor *palcolor; char *name = BLI_ghashIterator_getKey(&gh_iter); - + /* Look for existing color to map to */ /* XXX: What to do if same name but different color? Behaviour here should depend on a property? */ palcolor = BKE_gpencil_palettecolor_getbyname(palette, name); @@ -398,17 +398,17 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd) /* Doesn't Exist - Create new matching color for this palette */ /* XXX: This still doesn't fix the pasting across file boundaries problem... */ bGPDpalettecolor *src_color = BLI_ghashIterator_getValue(&gh_iter); - + palcolor = MEM_dupallocN(src_color); BLI_addtail(&palette->colors, palcolor); - + BLI_uniquename(&palette->colors, palcolor, DATA_("GP Color"), '.', offsetof(bGPDpalettecolor, info), sizeof(palcolor->info)); } - + /* Store this mapping (for use later when pasting) */ BLI_ghash_insert(new_colors, name, palcolor); } - + return new_colors; } @@ -418,15 +418,15 @@ GHash *gp_copybuf_validate_colormap(bGPdata *gpd) static int gp_strokes_copy_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); return OPERATOR_CANCELLED; } - + /* clear the buffer first */ ED_gpencil_strokes_copybuf_free(); - + /* for each visible (and editable) layer's selected strokes, * copy the strokes into a temporary buffer, then append * once all done @@ -435,31 +435,31 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps; - + if (gpf == NULL) continue; - + /* make copies of selected strokes, and deselect these once we're done */ for (gps = gpf->strokes.first; gps; gps = gps->next) { /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; - + if (gps->flag & GP_STROKE_SELECT) { if (gps->totpoints == 1) { /* Special Case: If there's just a single point in this stroke... */ bGPDstroke *gpsd; - + /* make direct copies of the stroke and its points */ gpsd = MEM_dupallocN(gps); BLI_strncpy(gpsd->tmp_layerinfo, gpl->info, sizeof(gpsd->tmp_layerinfo)); /* saves original layer name */ gpsd->points = MEM_dupallocN(gps->points); - + /* triangles cache - will be recalculated on next redraw */ gpsd->flag |= GP_STROKE_RECALC_CACHES; gpsd->tot_triangles = 0; gpsd->triangles = NULL; - + /* add to temp buffer */ gpsd->next = gpsd->prev = NULL; BLI_addtail(&gp_strokes_copypastebuf, gpsd); @@ -472,26 +472,26 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) } } CTX_DATA_END; - + /* Build up hash of colors used in these strokes, making copies of these to protect against dangling pointers */ if (gp_strokes_copypastebuf.first) { gp_strokes_copypastebuf_colors = BLI_ghash_str_new("GPencil CopyBuf Colors"); - + for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { if (BLI_ghash_haskey(gp_strokes_copypastebuf_colors, gps->colorname) == false) { bGPDpalettecolor *color = MEM_dupallocN(gps->palcolor); - + BLI_ghash_insert(gp_strokes_copypastebuf_colors, gps->colorname, color); gps->palcolor = color; } } } } - + /* updates (to ensure operator buttons are refreshed, when used via hotkeys) */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL); // XXX? - + /* done */ return OPERATOR_FINISHED; } @@ -502,11 +502,11 @@ void GPENCIL_OT_copy(wmOperatorType *ot) ot->name = "Copy Strokes"; ot->idname = "GPENCIL_OT_copy"; ot->description = "Copy selected Grease Pencil points and strokes"; - + /* callbacks */ ot->exec = gp_strokes_copy_exec; ot->poll = gp_stroke_edit_poll; - + /* flags */ //ot->flag = OPTYPE_REGISTER; } @@ -535,10 +535,10 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); /* only use active for copy merge */ bGPDframe *gpf; - + eGP_PasteMode type = RNA_enum_get(op->ptr, "type"); GHash *new_colors; - + /* check for various error conditions */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); @@ -560,14 +560,14 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) /* Check that some of the strokes in the buffer can be used */ bGPDstroke *gps; bool ok = false; - + for (gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { ok = true; break; } } - + if (ok == false) { /* XXX: this check is not 100% accurate (i.e. image editor is incompatible with normal 2D strokes), * but should be enough to give users a good idea of what's going on @@ -576,28 +576,28 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot paste 2D strokes in 3D View"); else BKE_report(op->reports, RPT_ERROR, "Cannot paste 3D strokes in 2D editors"); - + return OPERATOR_CANCELLED; } } - + /* Deselect all strokes first */ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } - + gps->flag &= ~GP_STROKE_SELECT; } CTX_DATA_END; - + /* Ensure that all the necessary colors exist */ new_colors = gp_copybuf_validate_colormap(gpd); - + /* Copy over the strokes from the buffer (and adjust the colors) */ for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { @@ -609,7 +609,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) gpl = CTX_data_active_gpencil_layer(C); } } - + /* Ensure we have a frame to draw into * NOTE: Since this is an op which creates strokes, * we are obliged to add a new frame if one @@ -620,33 +620,33 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op) /* Create new stroke */ bGPDstroke *new_stroke = MEM_dupallocN(gps); new_stroke->tmp_layerinfo[0] = '\0'; - + new_stroke->points = MEM_dupallocN(gps->points); - + new_stroke->flag |= GP_STROKE_RECALC_CACHES; new_stroke->triangles = NULL; - + new_stroke->next = new_stroke->prev = NULL; BLI_addtail(&gpf->strokes, new_stroke); - + /* Fix color references */ BLI_assert(new_stroke->colorname[0] != '\0'); new_stroke->palcolor = BLI_ghash_lookup(new_colors, new_stroke->colorname); - + BLI_assert(new_stroke->palcolor != NULL); BLI_strncpy(new_stroke->colorname, new_stroke->palcolor->info, sizeof(new_stroke->colorname)); - + /*new_stroke->flag |= GP_STROKE_RECALC_COLOR; */ } } } - + /* free temp data */ BLI_ghash_free(new_colors, NULL, NULL); - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -657,19 +657,19 @@ void GPENCIL_OT_paste(wmOperatorType *ot) {GP_COPY_MERGE, "MERGE", 0, "Merge", ""}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Paste Strokes"; ot->idname = "GPENCIL_OT_paste"; ot->description = "Paste previously copied strokes or copy and merge in active layer"; - + /* callbacks */ ot->exec = gp_strokes_paste_exec; ot->poll = gp_strokes_paste_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", ""); } @@ -680,13 +680,13 @@ static int gp_move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *U { uiPopupMenu *pup; uiLayout *layout; - + /* call the menu, which will call this operator again, hence the canceled */ pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE); layout = UI_popup_menu_layout(pup); uiItemsEnumO(layout, "GPENCIL_OT_move_to_layer", "layer"); UI_popup_menu_end(C, pup); - + return OPERATOR_INTERFACE; } @@ -697,7 +697,7 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) bGPDlayer *target_layer = NULL; ListBase strokes = {NULL, NULL}; int layer_num = RNA_enum_get(op->ptr, "layer"); - + /* Get layer or create new one */ if (layer_num == -1) { /* Create layer */ @@ -706,13 +706,13 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) else { /* Try to get layer */ target_layer = BLI_findlink(&gpd->layers, layer_num); - + if (target_layer == NULL) { BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num); return OPERATOR_CANCELLED; } } - + /* Extract all strokes to move to this layer * NOTE: We need to do this in a two-pass system to avoid conflicts with strokes * getting repeatedly moved @@ -721,19 +721,19 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + /* skip if no frame with strokes, or if this is the layer we're moving strokes to */ if ((gpl == target_layer) || (gpf == NULL)) continue; - + /* make copies of selected strokes, and deselect these once we're done */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; - + /* TODO: Don't just move entire strokes - instead, only copy the selected portions... */ if (gps->flag & GP_STROKE_SELECT) { BLI_remlink(&gpf->strokes, gps); @@ -742,19 +742,19 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) } } CTX_DATA_END; - + /* Paste them all in one go */ if (strokes.first) { Scene *scene = CTX_data_scene(C); bGPDframe *gpf = BKE_gpencil_layer_getframe(target_layer, CFRA, true); - + BLI_movelisttolist(&gpf->strokes, &strokes); BLI_assert((strokes.first == strokes.last) && (strokes.first == NULL)); } - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -764,15 +764,15 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) ot->name = "Move Strokes to Layer"; ot->idname = "GPENCIL_OT_move_to_layer"; ot->description = "Move selected strokes to another layer"; // XXX: allow moving individual points too? - + /* callbacks */ ot->invoke = gp_move_to_layer_invoke; ot->exec = gp_move_to_layer_exec; ot->poll = gp_stroke_edit_poll; // XXX? - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* gp layer to use (dynamic enum) */ ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", ""); RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf); @@ -795,7 +795,7 @@ static int UNUSED_FUNCTION(gp_blank_frame_add_poll)(bContext *C) else { CTX_wm_operator_poll_msg_set(C, "Active region not set"); } - + return 0; } @@ -812,8 +812,8 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) /* let's just be lazy, and call the "Add New Layer" operator, which sets everything up as required */ WM_operator_name_call(C, "GPENCIL_OT_layer_add", WM_OP_EXEC_DEFAULT, NULL); } - - /* Go through each layer, adding a frame after the active one + + /* Go through each layer, adding a frame after the active one * and/or shunting all the others out of the way */ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) @@ -830,15 +830,15 @@ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) gpf->framenum += 1; } } - + /* 2) Now add a new frame, with nothing in it */ gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_NEW); } CTX_DATA_END; - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -849,11 +849,11 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) ot->idname = "GPENCIL_OT_blank_frame_add"; ot->description = "Insert a blank frame on the current frame " "(all subsequently existing frames, if any, are shifted right by one frame)"; - + /* callbacks */ ot->exec = gp_blank_frame_add_exec; ot->poll = gp_add_poll; - + /* properties */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "all_layers", false, "All Layers", "Create blank frame in all layers, not only active"); @@ -865,7 +865,7 @@ static int gp_actframe_delete_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + /* only if there's an active layer with an active frame */ return (gpl && gpl->actframe); } @@ -877,7 +877,7 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); - + /* if there's no existing Grease-Pencil data there, add some */ if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No grease pencil data"); @@ -887,13 +887,13 @@ static int gp_actframe_delete_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "No active frame to delete"); return OPERATOR_CANCELLED; } - + /* delete it... */ BKE_gpencil_layer_delframe(gpl, gpf); - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -903,9 +903,9 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot) ot->name = "Delete Active Frame"; ot->idname = "GPENCIL_OT_active_frame_delete"; ot->description = "Delete the active frame for the active Grease Pencil Layer"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_actframe_delete_exec; ot->poll = gp_actframe_delete_poll; @@ -916,7 +916,7 @@ void GPENCIL_OT_active_frame_delete(wmOperatorType *ot) static int gp_actframe_delete_all_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + /* 1) There must be grease pencil data * 2) Hopefully some of the layers have stuff we can use */ @@ -927,26 +927,26 @@ static int gp_actframe_delete_all_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); bool success = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { /* try to get the "active" frame - but only if it actually occurs on this frame */ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); - + if (gpf == NULL) continue; - + /* delete it... */ BKE_gpencil_layer_delframe(gpl, gpf); - + /* we successfully modified something */ success = true; } CTX_DATA_END; - + /* updates */ if (success) { - WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } else { @@ -961,9 +961,9 @@ void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot) ot->name = "Delete All Active Frames"; ot->idname = "GPENCIL_OT_active_frames_delete_all"; ot->description = "Delete the active frame(s) of all editable Grease Pencil layers"; - + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* callbacks */ ot->exec = gp_actframe_delete_all_exec; ot->poll = gp_actframe_delete_all_poll; @@ -986,36 +986,36 @@ typedef enum eGP_DeleteMode { static int gp_delete_selected_strokes(bContext *C) { bool changed = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + if (gpf == NULL) continue; - + /* simply delete strokes which are selected */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; - + /* free stroke if selected */ if (gps->flag & GP_STROKE_SELECT) { /* free stroke memory arrays, then stroke itself */ if (gps->points) MEM_freeN(gps->points); if (gps->triangles) MEM_freeN(gps->triangles); BLI_freelinkN(&gpf->strokes, gps); - + changed = true; } } } CTX_DATA_END; - + if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -1031,34 +1031,34 @@ static int gp_delete_selected_strokes(bContext *C) static int gp_dissolve_selected_points(bContext *C) { bool changed = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + if (gpf == NULL) continue; - + /* simply delete points from selected strokes * NOTE: we may still have to remove the stroke if it ends up having no points! */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; /* check if the color is editable */ if (ED_gpencil_stroke_color_use(gpl, gps) == false) continue; - + if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; - + int tot = gps->totpoints; /* number of points in new buffer */ - + /* First Pass: Count how many points are selected (i.e. how many to remove) */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { @@ -1066,7 +1066,7 @@ static int gp_dissolve_selected_points(bContext *C) tot--; } } - + /* if no points are left, we simply delete the entire stroke */ if (tot <= 0) { /* remove the entire stroke */ @@ -1080,35 +1080,35 @@ static int gp_dissolve_selected_points(bContext *C) /* just copy all unselected into a smaller buffer */ bGPDspoint *new_points = MEM_callocN(sizeof(bGPDspoint) * tot, "new gp stroke points copy"); bGPDspoint *npt = new_points; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if ((pt->flag & GP_SPOINT_SELECT) == 0) { *npt = *pt; npt++; } } - + /* free the old buffer */ MEM_freeN(gps->points); - + /* save the new buffer */ gps->points = new_points; gps->totpoints = tot; - + /* triangles cache needs to be recalculated */ gps->flag |= GP_STROKE_RECALC_CACHES; gps->tot_triangles = 0; - + /* deselect the stroke, since none of its selected points will still be selected */ gps->flag &= ~GP_STROKE_SELECT; } - + changed = true; } } } CTX_DATA_END; - + if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -1148,10 +1148,10 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke tGPDeleteIsland *islands = MEM_callocN(sizeof(tGPDeleteIsland) * (gps->totpoints + 1) / 2, "gp_point_islands"); bool in_island = false; int num_islands = 0; - + bGPDspoint *pt; int i; - + /* First Pass: Identify start/end of islands */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & tag_flags) { @@ -1161,7 +1161,7 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke else { /* unselected - start of a new island? */ int idx; - + if (in_island) { /* extend existing island */ idx = num_islands - 1; @@ -1171,37 +1171,37 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke /* start of new island */ in_island = true; num_islands++; - + idx = num_islands - 1; islands[idx].start_idx = islands[idx].end_idx = i; } } } - + /* Watch out for special case where No islands = All points selected = Delete Stroke only */ if (num_islands) { /* there are islands, so create a series of new strokes, adding them before the "next" stroke */ int idx; - + /* Create each new stroke... */ for (idx = 0; idx < num_islands; idx++) { tGPDeleteIsland *island = &islands[idx]; bGPDstroke *new_stroke = MEM_dupallocN(gps); - + /* initialize triangle memory - to be calculated on next redraw */ new_stroke->triangles = NULL; new_stroke->flag |= GP_STROKE_RECALC_CACHES; new_stroke->tot_triangles = 0; - + /* Compute new buffer size (+ 1 needed as the endpoint index is "inclusive") */ new_stroke->totpoints = island->end_idx - island->start_idx + 1; new_stroke->points = MEM_callocN(sizeof(bGPDspoint) * new_stroke->totpoints, "gp delete stroke fragment"); - + /* Copy over the relevant points */ memcpy(new_stroke->points, gps->points + island->start_idx, sizeof(bGPDspoint) * new_stroke->totpoints); - - - /* Each island corresponds to a new stroke. We must adjust the + + + /* Each island corresponds to a new stroke. We must adjust the * timings of these new strokes: * * Each point's timing data is a delta from stroke's inittime, so as we erase some points from @@ -1213,15 +1213,15 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke bGPDspoint *pts; float delta = gps->points[island->start_idx].time; int j; - + new_stroke->inittime += (double)delta; - + pts = new_stroke->points; for (j = 0; j < new_stroke->totpoints; j++, pts++) { pts->time -= delta; } } - + /* Add new stroke to the frame */ if (next_stroke) { BLI_insertlinkbefore(&gpf->strokes, next_stroke, new_stroke); @@ -1231,10 +1231,10 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke } } } - + /* free islands */ MEM_freeN(islands); - + /* Delete the old stroke */ MEM_freeN(gps->points); if (gps->triangles) { @@ -1248,40 +1248,40 @@ void gp_stroke_delete_tagged_points(bGPDframe *gpf, bGPDstroke *gps, bGPDstroke static int gp_delete_selected_points(bContext *C) { bool changed = false; - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = gpl->actframe; bGPDstroke *gps, *gpsn; - + if (gpf == NULL) continue; - + /* simply delete strokes which are selected */ for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; /* check if the color is editable */ if (ED_gpencil_stroke_color_use(gpl, gps) == false) continue; - - + + if (gps->flag & GP_STROKE_SELECT) { /* deselect old stroke, since it will be used as template for the new strokes */ gps->flag &= ~GP_STROKE_SELECT; - + /* delete unwanted points by splitting stroke into several smaller ones */ gp_stroke_delete_tagged_points(gpf, gps, gpsn, GP_SPOINT_SELECT); - + changed = true; } } } CTX_DATA_END; - + if (changed) { WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; @@ -1297,21 +1297,21 @@ static int gp_delete_exec(bContext *C, wmOperator *op) { eGP_DeleteMode mode = RNA_enum_get(op->ptr, "type"); int result = OPERATOR_CANCELLED; - + switch (mode) { case GP_DELETEOP_STROKES: /* selected strokes */ result = gp_delete_selected_strokes(C); break; - + case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */ result = gp_delete_selected_points(C); break; - + case GP_DELETEOP_FRAME: /* active frame */ result = gp_actframe_delete_exec(C, op); break; } - + return result; } @@ -1323,20 +1323,20 @@ void GPENCIL_OT_delete(wmOperatorType *ot) {GP_DELETEOP_FRAME, "FRAME", 0, "Frame", "Delete active frame"}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Delete"; ot->idname = "GPENCIL_OT_delete"; ot->description = "Delete selected Grease Pencil strokes, vertices, or frames"; - + /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_delete_exec; ot->poll = gp_stroke_edit_poll; - + /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; - + /* props */ ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_delete_types, 0, "Type", "Method used for deleting Grease Pencil data"); } @@ -1371,7 +1371,7 @@ static int gp_snap_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); ScrArea *sa = CTX_wm_area(C); - + return (gpd != NULL) && ((sa != NULL) && (sa->spacetype == SPACE_VIEW3D)); } @@ -1382,29 +1382,29 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) bGPdata *gpd = ED_gpencil_data_get_active(C); RegionView3D *rv3d = CTX_wm_region_data(C); const float gridf = rv3d->gridview; - + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; float diff_mat[4][4]; - + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); } - + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { bGPDspoint *pt; int i; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; /* check if the color is editable */ if (ED_gpencil_stroke_color_use(gpl, gps) == false) continue; - + // TODO: if entire stroke is selected, offset entire stroke by same amount? for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { /* only if point is selected */ @@ -1418,11 +1418,11 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) /* apply parent transformations */ float fpt[3]; mul_v3_m4v3(fpt, diff_mat, &pt->x); - + fpt[0] = gridf * floorf(0.5f + fpt[0] / gridf); fpt[1] = gridf * floorf(0.5f + fpt[1] / gridf); fpt[2] = gridf * floorf(0.5f + fpt[2] / gridf); - + /* return data */ copy_v3_v3(&pt->x, fpt); gp_apply_parent_point(gpl, pt); @@ -1432,7 +1432,7 @@ static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) } } } - + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -1443,11 +1443,11 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) ot->name = "Snap Selection to Grid"; ot->idname = "GPENCIL_OT_snap_to_grid"; ot->description = "Snap selected points to the nearest grid points"; - + /* callbacks */ ot->exec = gp_snap_to_grid; ot->poll = gp_snap_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -1457,28 +1457,28 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) static int gp_snap_to_cursor(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - + const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d); - + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; float diff_mat[4][4]; - + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); } - + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { bGPDspoint *pt; int i; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; @@ -1488,14 +1488,14 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op) /* only continue if this stroke is selected (editable doesn't guarantee this)... */ if ((gps->flag & GP_STROKE_SELECT) == 0) continue; - + if (use_offset) { float offset[3]; - + /* compute offset from first point of stroke to cursor */ /* TODO: Allow using midpoint instead? */ sub_v3_v3v3(offset, cursor_global, &gps->points->x); - + /* apply offset to all points in the stroke */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { add_v3_v3(&pt->x, offset); @@ -1513,10 +1513,10 @@ static int gp_snap_to_cursor(bContext *C, wmOperator *op) } } } - + } } - + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -1527,14 +1527,14 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) ot->name = "Snap Selection to Cursor"; ot->idname = "GPENCIL_OT_snap_to_cursor"; ot->description = "Snap selected points/strokes to the cursor"; - + /* callbacks */ ot->exec = gp_snap_to_cursor; ot->poll = gp_snap_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ ot->prop = RNA_def_boolean(ot->srna, "use_offset", true, "With Offset", "Offset the entire stroke instead of selected points only"); @@ -1545,33 +1545,33 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); - + float *cursor = ED_view3d_cursor3d_get(scene, v3d); float centroid[3] = {0.0f}; float min[3], max[3]; size_t count = 0; - + INIT_MINMAX(min, max); - + /* calculate midpoints from selected points */ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { bGPDframe *gpf = gpl->actframe; float diff_mat[4][4]; - + /* calculate difference matrix if parent object */ if (gpl->parent != NULL) { ED_gpencil_parent_location(gpl, diff_mat); } - + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { bGPDspoint *pt; int i; - + /* skip strokes that are invalid for current view */ if (ED_gpencil_stroke_can_use(C, gps) == false) continue; @@ -1581,7 +1581,7 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) /* only continue if this stroke is selected (editable doesn't guarantee this)... */ if ((gps->flag & GP_STROKE_SELECT) == 0) continue; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { if (pt->flag & GP_SPOINT_SELECT) { if (gpl->parent == NULL) { @@ -1592,18 +1592,18 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) /* apply parent transformations */ float fpt[3]; mul_v3_m4v3(fpt, diff_mat, &pt->x); - + add_v3_v3(centroid, fpt); minmax_v3v3_v3(min, max, fpt); } count++; } } - + } } } - + if (v3d->around == V3D_AROUND_CENTER_MEAN && count) { mul_v3_fl(centroid, 1.0f / (float)count); copy_v3_v3(cursor, centroid); @@ -1612,7 +1612,7 @@ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) mid_v3_v3v3(cursor, min, max); } - + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -1623,11 +1623,11 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot) ot->name = "Snap Cursor to Selected Points"; ot->idname = "GPENCIL_OT_snap_cursor_to_selected"; ot->description = "Snap cursor to center of selected points"; - + /* callbacks */ ot->exec = gp_snap_cursor_to_sel; ot->poll = gp_snap_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -1683,27 +1683,27 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); const int type = RNA_enum_get(op->ptr, "type"); - + /* sanity checks */ if (ELEM(NULL, gpd)) return OPERATOR_CANCELLED; - + /* loop all selected strokes */ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { if (gpl->actframe == NULL) continue; - + for (bGPDstroke *gps = gpl->actframe->strokes.last; gps; gps = gps->prev) { bGPDpalettecolor *palcolor = gps->palcolor; - + /* skip strokes that are not selected or invalid for current view */ if (((gps->flag & GP_STROKE_SELECT) == 0) || ED_gpencil_stroke_can_use(C, gps) == false) continue; /* skip hidden or locked colors */ if (!palcolor || (palcolor->flag & PC_COLOR_HIDE) || (palcolor->flag & PC_COLOR_LOCKED)) continue; - + switch (type) { case GP_STROKE_CYCLIC_CLOSE: /* Close all (enable) */ @@ -1724,10 +1724,10 @@ static int gp_stroke_cyclical_set_exec(bContext *C, wmOperator *op) } } CTX_DATA_END; - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -1743,19 +1743,19 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) {GP_STROKE_CYCLIC_TOGGLE, "TOGGLE", 0, "Toggle", ""}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Set Cyclical State"; ot->idname = "GPENCIL_OT_stroke_cyclical_set"; ot->description = "Close or open the selected stroke adding an edge from last to first point"; - + /* api callbacks */ ot->exec = gp_stroke_cyclical_set_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", cyclic_type, GP_STROKE_CYCLIC_TOGGLE, "Type", ""); } @@ -1766,11 +1766,11 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) static void gpencil_flip_stroke(bGPDstroke *gps) { int end = gps->totpoints - 1; - + for (int i = 0; i < gps->totpoints / 2; i++) { bGPDspoint *point, *point2; bGPDspoint pt; - + /* save first point */ point = &gps->points[i]; pt.x = point->x; @@ -1780,7 +1780,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps) pt.pressure = point->pressure; pt.strength = point->strength; pt.time = point->time; - + /* replace first point with last point */ point2 = &gps->points[end]; point->x = point2->x; @@ -1790,7 +1790,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps) point->pressure = point2->pressure; point->strength = point2->strength; point->time = point2->time; - + /* replace last point with first saved before */ point = &gps->points[end]; point->x = pt.x; @@ -1800,7 +1800,7 @@ static void gpencil_flip_stroke(bGPDstroke *gps) point->pressure = pt.pressure; point->strength = pt.strength; point->time = pt.time; - + end--; } } @@ -1810,10 +1810,10 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, bGPDspoint *point, float float pressure, float strength, float deltatime) { bGPDspoint *newpoint; - + gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); gps->totpoints++; - + newpoint = &gps->points[gps->totpoints - 1]; newpoint->x = point->x * delta[0]; newpoint->y = point->y * delta[1]; @@ -1832,28 +1832,28 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, co int i; float delta[3] = {1.0f, 1.0f, 1.0f}; float deltatime = 0.0f; - + /* sanity checks */ if (ELEM(NULL, gps_a, gps_b)) return; - + if ((gps_a->totpoints == 0) || (gps_b->totpoints == 0)) return; - + /* define start and end points of each stroke */ float sa[3], sb[3], ea[3], eb[3]; pt = &gps_a->points[0]; copy_v3_v3(sa, &pt->x); - + pt = &gps_a->points[gps_a->totpoints - 1]; copy_v3_v3(ea, &pt->x); - + pt = &gps_b->points[0]; copy_v3_v3(sb, &pt->x); - + pt = &gps_b->points[gps_b->totpoints - 1]; copy_v3_v3(eb, &pt->x); - + /* review if need flip stroke B */ float ea_sb = len_squared_v3v3(ea, sb); float ea_eb = len_squared_v3v3(ea, eb); @@ -1861,19 +1861,19 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, bGPDstroke *gps_b, co if (ea_eb < ea_sb) { gpencil_flip_stroke(gps_b); } - + /* don't visibly link the first and last points? */ if (leave_gaps) { /* 1st: add one tail point to start invisible area */ point = gps_a->points[gps_a->totpoints - 1]; deltatime = point.time; gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, 0.0f); - + /* 2nd: add one head point to finish invisible area */ point = gps_b->points[0]; gpencil_stroke_copy_point(gps_a, &point, delta, 0.0f, 0.0f, deltatime); } - + /* 3rd: add all points */ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { /* check if still room in buffer */ @@ -1890,25 +1890,25 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) bGPDstroke *gps, *gpsn; bGPDpalette *palette = BKE_gpencil_palette_getactive(gpd); bGPDpalettecolor *palcolor = BKE_gpencil_palettecolor_getactive(palette); - + bGPDframe *gpf_a = NULL; bGPDstroke *stroke_a = NULL; bGPDstroke *stroke_b = NULL; bGPDstroke *new_stroke = NULL; - + const int type = RNA_enum_get(op->ptr, "type"); const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps"); - + /* sanity checks */ if (ELEM(NULL, gpd)) return OPERATOR_CANCELLED; - + if (activegpl->flag & GP_LAYER_LOCKED) return OPERATOR_CANCELLED; - + BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY)); - - + + /* read all selected strokes */ bool first = false; CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) @@ -1916,7 +1916,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) bGPDframe *gpf = gpl->actframe; if (gpf == NULL) continue; - + for (gps = gpf->strokes.first; gps; gps = gpsn) { gpsn = gps->next; if (gps->flag & GP_STROKE_SELECT) { @@ -1928,10 +1928,10 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_color_use(gpl, gps) == false) { continue; } - + /* to join strokes, cyclic must be disabled */ gps->flag &= ~GP_STROKE_CYCLIC; - + /* saves first frame and stroke */ if (!first) { first = true; @@ -1940,7 +1940,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) } else { stroke_b = gps; - + /* create a new stroke if was not created before (only created if something to join) */ if (new_stroke == NULL) { new_stroke = MEM_dupallocN(stroke_a); @@ -1948,7 +1948,7 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) new_stroke->triangles = NULL; new_stroke->tot_triangles = 0; new_stroke->flag |= GP_STROKE_RECALC_CACHES; - + /* if new, set current color */ if (type == GP_STROKE_JOINCOPY) { new_stroke->palcolor = palcolor; @@ -1956,10 +1956,10 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) new_stroke->flag |= GP_STROKE_RECALC_COLOR; } } - + /* join new_stroke and stroke B. New stroke will contain all the previous data */ gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps); - + /* if join only, delete old strokes */ if (type == GP_STROKE_JOIN) { if (stroke_a) { @@ -1979,21 +1979,21 @@ static int gp_stroke_join_exec(bContext *C, wmOperator *op) } } CTX_DATA_END; - + /* add new stroke if was not added before */ if (type == GP_STROKE_JOINCOPY) { if (new_stroke) { /* Add a new frame if needed */ if (activegpl->actframe == NULL) activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum); - + BLI_addtail(&activegpl->actframe->strokes, new_stroke); } } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -2004,19 +2004,19 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot) {GP_STROKE_JOINCOPY, "JOINCOPY", 0, "Join and Copy", ""}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Join Strokes"; ot->idname = "GPENCIL_OT_stroke_join"; ot->description = "Join selected strokes (optionally as new stroke)"; - + /* api callbacks */ ot->exec = gp_stroke_join_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", join_type, GP_STROKE_JOIN, "Type", ""); RNA_def_boolean(ot->srna, "leave_gaps", false, "Leave Gaps", "Leave gaps between joined strokes instead of linking them"); @@ -2038,7 +2038,7 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) bGPDframe *gpf = gpl->actframe; if (gpf == NULL) continue; - + for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { if (gps->flag & GP_STROKE_SELECT) { /* skip strokes that are invalid for current view */ @@ -2049,17 +2049,17 @@ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) if (ED_gpencil_stroke_color_use(gpl, gps) == false) { continue; } - + /* flip stroke */ gpencil_flip_stroke(gps); } } } CTX_DATA_END; - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -2069,11 +2069,11 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot) ot->name = "Flip Stroke"; ot->idname = "GPENCIL_OT_stroke_flip"; ot->description = "Change direction of the points of the selected strokes"; - + /* api callbacks */ ot->exec = gp_stroke_flip_exec; ot->poll = gp_active_layer_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -2101,18 +2101,18 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); GP_SpaceConversion gsc = {NULL}; eGP_ReprojectModes mode = RNA_boolean_get(op->ptr, "type"); - + /* init space conversion stuff */ gp_point_conversion_init(C, &gsc); - + /* init autodist for geometry projection */ if (mode == GP_REPROJECT_SURFACE) { view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar); ED_view3d_autodist_init(scene, gsc.ar, CTX_wm_view3d(C), 0); } - + // TODO: For deforming geometry workflow, create new frames? - + /* Go through each editable + selected stroke, adjusting each of its points one by one... */ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) { @@ -2120,17 +2120,17 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) bGPDspoint *pt; int i; float inverse_diff_mat[4][4]; - + /* Compute inverse matrix for unapplying parenting once instead of doing per-point */ /* TODO: add this bit to the iteration macro? */ if (gpl->parent) { invert_m4_m4(inverse_diff_mat, diff_mat); } - + /* Adjust each point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { float xy[2]; - + /* 3D to Screenspace */ /* Note: We can't use gp_point_to_xy() here because that uses ints for the screenspace * coordinates, resulting in lost precision, which in turn causes stairstepping @@ -2144,7 +2144,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) gp_point_to_parent_space(pt, diff_mat, &pt2); gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]); } - + /* Project screenspace back to 3D space (from current perspective) * so that all points have been treated the same way */ @@ -2156,10 +2156,10 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) /* Geometry - Snap to surfaces of visible geometry */ /* XXX: There will be precision loss (possible stairstep artifacts) from this conversion to satisfy the API's */ const int screen_co[2] = {(int)xy[0], (int)xy[1]}; - + int depth_margin = 0; // XXX: 4 for strokes, 0 for normal float depth; - + /* XXX: The proper procedure computes the depths into an array, to have smooth transitions when all else fails... */ if (ED_view3d_autodist_depth(gsc.ar, screen_co, depth_margin, &depth)) { ED_view3d_autodist_simple(gsc.ar, screen_co, &pt->x, 0, &depth); @@ -2169,7 +2169,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) gp_point_xy_to_3d(&gsc, scene, xy, &pt->x); } } - + /* Unapply parent corrections */ if (gpl->parent) { mul_m4_v3(inverse_diff_mat, &pt->x); @@ -2178,7 +2178,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) } } GP_EDITABLE_STROKES_END; - + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); return OPERATOR_FINISHED; } @@ -2186,29 +2186,29 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op) void GPENCIL_OT_reproject(wmOperatorType *ot) { static const EnumPropertyItem reproject_type[] = { - {GP_REPROJECT_PLANAR, "PLANAR", 0, "Planar", + {GP_REPROJECT_PLANAR, "PLANAR", 0, "Planar", "Reproject the strokes to end up on the same plane, as if drawn from the current viewpoint " "using 'Cursor' Stroke Placement"}, {GP_REPROJECT_SURFACE, "SURFACE", 0, "Surface", "Reproject the strokes on to the scene geometry, as if drawn using 'Surface' placement"}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Reproject Strokes"; ot->idname = "GPENCIL_OT_reproject"; ot->description = "Reproject the selected strokes from the current viewpoint as if they had been newly drawn " "(e.g. to fix problems from accidental 3D cursor movement or accidental viewport changes, " "or for matching deforming geometry)"; - + /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_strokes_reproject_exec; ot->poll = gp_strokes_reproject_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", reproject_type, GP_REPROJECT_PLANAR, "Projection Type", ""); } diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 83e2a85db49..ff3f5b20858 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -89,18 +89,18 @@ static int gpencil_view3d_poll(bContext *C) { bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *gpl = CTX_data_active_gpencil_layer(C); - + /* only 3D view */ ScrArea *sa = CTX_wm_area(C); if (sa && sa->spacetype != SPACE_VIEW3D) { return 0; } - + /* need data to interpolate */ if (ELEM(NULL, gpd, gpl)) { return 0; } - + return 1; } @@ -108,13 +108,13 @@ static int gpencil_view3d_poll(bContext *C) static void gp_interpolate_update_points(bGPDstroke *gps_from, bGPDstroke *gps_to, bGPDstroke *new_stroke, float factor) { bGPDspoint *prev, *pt, *next; - + /* update points */ for (int i = 0; i < new_stroke->totpoints; i++) { prev = &gps_from->points[i]; pt = &new_stroke->points[i]; next = &gps_to->points[i]; - + /* Interpolate all values */ interp_v3_v3v3(&pt->x, &prev->x, &next->x, factor); pt->pressure = interpf(prev->pressure, next->pressure, 1.0f - factor); @@ -130,32 +130,32 @@ static void gp_interpolate_update_strokes(bContext *C, tGPDinterpolate *tgpi) { tGPDinterpolate_layer *tgpil; const float shift = tgpi->shift; - + for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { bGPDstroke *new_stroke; const float factor = tgpil->factor + shift; - + for (new_stroke = tgpil->interFrame->strokes.first; new_stroke; new_stroke = new_stroke->next) { bGPDstroke *gps_from, *gps_to; int stroke_idx; - + if (new_stroke->totpoints == 0) { continue; } - + /* get strokes to interpolate */ stroke_idx = BLI_findindex(&tgpil->interFrame->strokes, new_stroke); - + gps_from = BLI_findlink(&tgpil->prevFrame->strokes, stroke_idx); gps_to = BLI_findlink(&tgpil->nextFrame->strokes, stroke_idx); - + /* update points position */ if ((gps_from) && (gps_to)) { gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); } } } - + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } @@ -164,7 +164,7 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) { ToolSettings *ts = CTX_data_tool_settings(C); eGP_Interpolate_SettingsFlag flag = ts->gp_interpolate.flag; - + /* get layers */ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { /* all layers or only active */ @@ -175,12 +175,12 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) { continue; } - + /* read strokes */ for (bGPDstroke *gps_from = gpl->actframe->strokes.first; gps_from; gps_from = gps_from->next) { bGPDstroke *gps_to; int fFrame; - + /* only selected */ if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; @@ -193,14 +193,14 @@ static bool gp_interpolate_check_todo(bContext *C, bGPdata *gpd) if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) { continue; } - + /* get final stroke to interpolate */ fFrame = BLI_findindex(&gpl->actframe->strokes, gps_from); gps_to = BLI_findlink(&gpl->actframe->next->strokes, fFrame); if (gps_to == NULL) { continue; } - + return true; } } @@ -213,18 +213,18 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) bGPdata *gpd = tgpi->gpd; bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C); bGPDframe *actframe = active_gpl->actframe; - + /* save initial factor for active layer to define shift limits */ tgpi->init_factor = (float)(tgpi->cframe - actframe->framenum) / (actframe->next->framenum - actframe->framenum + 1); - + /* limits are 100% below 0 and 100% over the 100% */ tgpi->low_limit = -1.0f - tgpi->init_factor; tgpi->high_limit = 2.0f - tgpi->init_factor; - + /* set layers */ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { tGPDinterpolate_layer *tgpil; - + /* all layers or only active */ if (!(tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) && (gpl != active_gpl)) { continue; @@ -233,32 +233,32 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) { continue; } - + /* create temp data for each layer */ tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer"); - + tgpil->gpl = gpl; tgpil->prevFrame = gpl->actframe; tgpil->nextFrame = gpl->actframe->next; - + BLI_addtail(&tgpi->ilayers, tgpil); - + /* create a new temporary frame */ tgpil->interFrame = MEM_callocN(sizeof(bGPDframe), "bGPDframe"); tgpil->interFrame->framenum = tgpi->cframe; - + /* get interpolation factor by layer (usually must be equal for all layers, but not sure) */ tgpil->factor = (float)(tgpi->cframe - tgpil->prevFrame->framenum) / (tgpil->nextFrame->framenum - tgpil->prevFrame->framenum + 1); - + /* create new strokes data with interpolated points reading original stroke */ for (bGPDstroke *gps_from = tgpil->prevFrame->strokes.first; gps_from; gps_from = gps_from->next) { bGPDstroke *gps_to; int fFrame; - + bGPDstroke *new_stroke; bool valid = true; - - + + /* only selected */ if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { valid = false; @@ -267,19 +267,19 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) if (ED_gpencil_stroke_can_use(C, gps_from) == false) { valid = false; } - + /* check if the color is editable */ if (ED_gpencil_stroke_color_use(tgpil->gpl, gps_from) == false) { valid = false; } - + /* get final stroke to interpolate */ fFrame = BLI_findindex(&tgpil->prevFrame->strokes, gps_from); gps_to = BLI_findlink(&tgpil->nextFrame->strokes, fFrame); if (gps_to == NULL) { valid = false; } - + /* create new stroke */ new_stroke = MEM_dupallocN(gps_from); new_stroke->points = MEM_dupallocN(gps_from->points); @@ -306,7 +306,7 @@ static void gp_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) new_stroke->triangles = MEM_recallocN(new_stroke->triangles, sizeof(*new_stroke->triangles)); new_stroke->flag |= GP_STROKE_RECALC_CACHES; } - + /* add to strokes */ BLI_addtail(&tgpil->interFrame->strokes, new_stroke); } @@ -339,14 +339,14 @@ static void gpencil_mouse_update_shift(tGPDinterpolate *tgpi, wmOperator *op, co { float mid = (float)(tgpi->ar->winx - tgpi->ar->winrct.xmin) / 2.0f; float mpos = event->x - tgpi->ar->winrct.xmin; - + if (mpos >= mid) { tgpi->shift = ((mpos - mid) * tgpi->high_limit) / mid; } else { tgpi->shift = tgpi->low_limit - ((mpos * tgpi->low_limit) / mid); } - + CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit); RNA_float_set(op->ptr, "shift", tgpi->shift); } @@ -357,19 +357,19 @@ static void gpencil_interpolate_status_indicators(tGPDinterpolate *p) Scene *scene = p->scene; char status_str[UI_MAX_DRAW_STR]; char msg_str[UI_MAX_DRAW_STR]; - + BLI_strncpy(msg_str, IFACE_("GPencil Interpolation: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/MOVE to adjust factor"), UI_MAX_DRAW_STR); - + if (hasNumInput(&p->num)) { char str_offs[NUM_STR_REP_LEN]; - + outputNumInput(&p->num, str_offs, &scene->unit); BLI_snprintf(status_str, sizeof(status_str), "%s: %s", msg_str, str_offs); } else { BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", msg_str, (int)((p->init_factor + p->shift) * 100.0f)); } - + ED_area_headerprint(p->sa, status_str); } @@ -391,7 +391,7 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op) { tGPDinterpolate *tgpi = op->customdata; tGPDinterpolate_layer *tgpil; - + /* don't assume that operator data exists at all */ if (tgpi) { /* remove drawing handler */ @@ -401,21 +401,21 @@ static void gpencil_interpolate_exit(bContext *C, wmOperator *op) if (tgpi->draw_handle_3d) { ED_region_draw_cb_exit(tgpi->ar->type, tgpi->draw_handle_3d); } - + /* clear status message area */ ED_area_headerprint(tgpi->sa, NULL); - + /* finally, free memory used by temp data */ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { BKE_gpencil_free_strokes(tgpil->interFrame); MEM_freeN(tgpil->interFrame); } - + BLI_freelistN(&tgpi->ilayers); MEM_freeN(tgpi); } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); - + /* clear pointer */ op->customdata = NULL; } @@ -425,24 +425,24 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte { ToolSettings *ts = CTX_data_tool_settings(C); bGPdata *gpd = CTX_data_gpencil_data(C); - + /* set current scene and window */ tgpi->scene = CTX_data_scene(C); tgpi->sa = CTX_wm_area(C); tgpi->ar = CTX_wm_region(C); tgpi->flag = ts->gp_interpolate.flag; - + /* set current frame number */ tgpi->cframe = tgpi->scene->r.cfra; - + /* set GP datablock */ tgpi->gpd = gpd; - + /* set interpolation weight */ tgpi->shift = RNA_float_get(op->ptr, "shift"); /* set layers */ gp_interpolate_set_points(C, tgpi); - + return 1; } @@ -450,10 +450,10 @@ static bool gp_interpolate_set_init_values(bContext *C, wmOperator *op, tGPDinte static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *op) { tGPDinterpolate *tgpi = MEM_callocN(sizeof(tGPDinterpolate), "GPencil Interpolate Data"); - + /* define initial values */ gp_interpolate_set_init_values(C, op, tgpi); - + /* return context data for running operator */ return tgpi; } @@ -462,7 +462,7 @@ static tGPDinterpolate *gp_session_init_interpolation(bContext *C, wmOperator *o static int gpencil_interpolate_init(bContext *C, wmOperator *op) { tGPDinterpolate *tgpi; - + /* check context */ tgpi = op->customdata = gp_session_init_interpolation(C, op); if (tgpi == NULL) { @@ -470,7 +470,7 @@ static int gpencil_interpolate_init(bContext *C, wmOperator *op) gpencil_interpolate_exit(C, op); return 0; } - + /* everything is now setup ok */ return 1; } @@ -492,19 +492,19 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer"); return OPERATOR_CANCELLED; } - + /* cannot interpolate in extremes */ if (ELEM(CFRA, actframe->framenum, actframe->next->framenum)) { BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames"); return OPERATOR_CANCELLED; } - + /* need editable strokes */ if (!gp_interpolate_check_todo(C, gpd)) { BKE_report(op->reports, RPT_ERROR, "Interpolation requires some editable strokes"); return OPERATOR_CANCELLED; } - + /* try to initialize context data needed */ if (!gpencil_interpolate_init(C, op)) { if (op->customdata) @@ -514,24 +514,24 @@ static int gpencil_interpolate_invoke(bContext *C, wmOperator *op, const wmEvent else { tgpi = op->customdata; } - + /* Enable custom drawing handlers - * It needs 2 handlers because strokes can in 3d space and screen space - * and each handler use different coord system + * It needs 2 handlers because strokes can in 3d space and screen space + * and each handler use different coord system */ tgpi->draw_handle_screen = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_screen, tgpi, REGION_DRAW_POST_PIXEL); tgpi->draw_handle_3d = ED_region_draw_cb_activate(tgpi->ar->type, gpencil_interpolate_draw_3d, tgpi, REGION_DRAW_POST_VIEW); - + /* set cursor to indicate modal */ WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR); - + /* update shift indicator in header */ gpencil_interpolate_status_indicators(tgpi); WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); - + /* add a modal handler for this operator */ WM_event_add_modal_handler(C, op); - + return OPERATOR_RUNNING_MODAL; } @@ -544,7 +544,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent bGPDstroke *gps_src, *gps_dst; tGPDinterpolate_layer *tgpil; const bool has_numinput = hasNumInput(&tgpi->num); - + switch (event->type) { case LEFTMOUSE: /* confirm */ case RETKEY: @@ -552,19 +552,19 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent /* return to normal cursor and header status */ ED_area_headerprint(tgpi->sa, NULL); WM_cursor_modal_restore(win); - + /* insert keyframes as required... */ for (tgpil = tgpi->ilayers.first; tgpil; tgpil = tgpil->next) { gpf_dst = BKE_gpencil_layer_getframe(tgpil->gpl, tgpi->cframe, GP_GETFRAME_ADD_NEW); gpf_dst->key_type = BEZT_KEYTYPE_BREAKDOWN; - + /* copy strokes */ BLI_listbase_clear(&gpf_dst->strokes); for (gps_src = tgpil->interFrame->strokes.first; gps_src; gps_src = gps_src->next) { if (gps_src->totpoints == 0) { continue; } - + /* make copy of source stroke, then adjust pointer to points too */ gps_dst = MEM_dupallocN(gps_src); gps_dst->points = MEM_dupallocN(gps_src->points); @@ -573,34 +573,34 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent BLI_addtail(&gpf_dst->strokes, gps_dst); } } - + /* clean up temp data */ gpencil_interpolate_exit(C, op); - + /* done! */ return OPERATOR_FINISHED; } - + case ESCKEY: /* cancel */ case RIGHTMOUSE: { /* return to normal cursor and header status */ ED_area_headerprint(tgpi->sa, NULL); WM_cursor_modal_restore(win); - + /* clean up temp data */ gpencil_interpolate_exit(C, op); - + /* canceled! */ return OPERATOR_CANCELLED; } - + case WHEELUPMOUSE: { tgpi->shift = tgpi->shift + 0.01f; CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit); RNA_float_set(op->ptr, "shift", tgpi->shift); - + /* update screen */ gpencil_interpolate_update(C, op, tgpi); break; @@ -610,7 +610,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent tgpi->shift = tgpi->shift - 0.01f; CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit); RNA_float_set(op->ptr, "shift", tgpi->shift); - + /* update screen */ gpencil_interpolate_update(C, op, tgpi); break; @@ -621,7 +621,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent if (has_numinput == false) { /* update shift based on position of mouse */ gpencil_mouse_update_shift(tgpi, op, event); - + /* update screen */ gpencil_interpolate_update(C, op, tgpi); } @@ -632,21 +632,21 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent if ((event->val == KM_PRESS) && handleNumInput(C, &tgpi->num, event)) { const float factor = tgpi->init_factor; float value; - + /* Grab shift from numeric input, and store this new value (the user see an int) */ value = (factor + tgpi->shift) * 100.0f; applyNumInput(&tgpi->num, &value); tgpi->shift = value / 100.0f; - + /* recalculate the shift to get the right value in the frame scale */ tgpi->shift = tgpi->shift - factor; - + CLAMP(tgpi->shift, tgpi->low_limit, tgpi->high_limit); RNA_float_set(op->ptr, "shift", tgpi->shift); - + /* update screen */ gpencil_interpolate_update(C, op, tgpi); - + break; } else { @@ -655,7 +655,7 @@ static int gpencil_interpolate_modal(bContext *C, wmOperator *op, const wmEvent } } } - + /* still running... */ return OPERATOR_RUNNING_MODAL; } @@ -673,16 +673,16 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) ot->name = "Grease Pencil Interpolation"; ot->idname = "GPENCIL_OT_interpolate"; ot->description = "Interpolate grease pencil strokes between frames"; - + /* callbacks */ ot->invoke = gpencil_interpolate_invoke; ot->modal = gpencil_interpolate_modal; ot->cancel = gpencil_interpolate_cancel; ot->poll = gpencil_view3d_poll; - + /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; - + /* properties */ RNA_def_float_percentage(ot->srna, "shift", 0.0f, -1.0f, 1.0f, "Shift", "Bias factor for which frame has more influence on the interpolated strokes", -0.9f, 0.9f); } @@ -695,14 +695,14 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting const float begin = 0.0f; const float change = 1.0f; const float duration = 1.0f; - + const float back = ipo_settings->back; const float amplitude = ipo_settings->amplitude; const float period = ipo_settings->period; - + eBezTriple_Easing easing = ipo_settings->easing; float result = time; - + switch (ipo_settings->type) { case GP_IPO_BACK: switch (easing) { @@ -715,7 +715,7 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_back_ease_in_out(time, begin, change, duration, back); break; - + default: /* default/auto: same as ease out */ result = BLI_easing_back_ease_out(time, begin, change, duration, back); break; @@ -733,13 +733,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_bounce_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease out */ result = BLI_easing_bounce_ease_out(time, begin, change, duration); break; } break; - + case GP_IPO_CIRC: switch (easing) { case BEZT_IPO_EASE_IN: @@ -751,7 +751,7 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_circ_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_circ_ease_in(time, begin, change, duration); break; @@ -769,13 +769,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_cubic_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_cubic_ease_in(time, begin, change, duration); break; } break; - + case GP_IPO_ELASTIC: switch (easing) { case BEZT_IPO_EASE_IN: @@ -787,13 +787,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period); break; - + default: /* default/auto: same as ease out */ result = BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); break; } break; - + case GP_IPO_EXPO: switch (easing) { case BEZT_IPO_EASE_IN: @@ -805,13 +805,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_expo_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_expo_ease_in(time, begin, change, duration); break; } break; - + case GP_IPO_QUAD: switch (easing) { case BEZT_IPO_EASE_IN: @@ -823,13 +823,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_quad_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_quad_ease_in(time, begin, change, duration); break; } break; - + case GP_IPO_QUART: switch (easing) { case BEZT_IPO_EASE_IN: @@ -841,13 +841,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_quart_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_quart_ease_in(time, begin, change, duration); break; } break; - + case GP_IPO_QUINT: switch (easing) { case BEZT_IPO_EASE_IN: @@ -859,13 +859,13 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_quint_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_quint_ease_in(time, begin, change, duration); break; } break; - + case GP_IPO_SINE: switch (easing) { case BEZT_IPO_EASE_IN: @@ -877,18 +877,18 @@ static float gp_interpolate_seq_easing_calc(GP_Interpolate_Settings *ipo_setting case BEZT_IPO_EASE_IN_OUT: result = BLI_easing_sine_ease_in_out(time, begin, change, duration); break; - + default: /* default/auto: same as ease in */ result = BLI_easing_sine_ease_in(time, begin, change, duration); break; } break; - + default: printf("%s: Unknown interpolation type - %d\n", __func__, ipo_settings->type); break; } - + return result; } @@ -897,12 +897,12 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) bGPdata *gpd = CTX_data_gpencil_data(C); bGPDlayer *active_gpl = CTX_data_active_gpencil_layer(C); bGPDframe *actframe = active_gpl->actframe; - + Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); GP_Interpolate_Settings *ipo_settings = &ts->gp_interpolate; eGP_Interpolate_SettingsFlag flag = ipo_settings->flag; - + /* cannot interpolate if not between 2 frames */ if (ELEM(NULL, actframe, actframe->next)) { BKE_report(op->reports, RPT_ERROR, "Cannot find a pair of grease pencil frames to interpolate between in active layer"); @@ -913,13 +913,13 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "Cannot interpolate as current frame already has existing grease pencil frames"); return OPERATOR_CANCELLED; } - + /* loop all layer to check if need interpolation */ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { bGPDframe *prevFrame, *nextFrame; bGPDstroke *gps_from, *gps_to; int cframe, fFrame; - + /* all layers or only active */ if (((flag & GP_TOOLFLAG_INTERPOLATE_ALL_LAYERS) == 0) && (gpl != active_gpl)) { continue; @@ -928,19 +928,19 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) if (!gpencil_layer_is_editable(gpl) || (gpl->actframe == NULL)) { continue; } - + /* store extremes */ prevFrame = gpl->actframe; nextFrame = gpl->actframe->next; - + /* Loop over intermediary frames and create the interpolation */ for (cframe = prevFrame->framenum + 1; cframe < nextFrame->framenum; cframe++) { bGPDframe *interFrame = NULL; float factor; - + /* get interpolation factor */ factor = (float)(cframe - prevFrame->framenum) / (nextFrame->framenum - prevFrame->framenum + 1); - + if (ipo_settings->type == GP_IPO_CURVEMAP) { /* custom curvemap */ if (ipo_settings->custom_ipo) { @@ -954,11 +954,11 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) /* easing equation... */ factor = gp_interpolate_seq_easing_calc(ipo_settings, factor); } - + /* create new strokes data with interpolated points reading original stroke */ for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) { bGPDstroke *new_stroke; - + /* only selected */ if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) && ((gps_from->flag & GP_STROKE_SELECT) == 0)) { continue; @@ -971,20 +971,20 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_color_use(gpl, gps_from) == false) { continue; } - + /* get final stroke to interpolate */ fFrame = BLI_findindex(&prevFrame->strokes, gps_from); gps_to = BLI_findlink(&nextFrame->strokes, fFrame); if (gps_to == NULL) { continue; } - + /* create a new frame if needed */ if (interFrame == NULL) { interFrame = BKE_gpencil_layer_getframe(gpl, cframe, GP_GETFRAME_ADD_NEW); interFrame->key_type = BEZT_KEYTYPE_BREAKDOWN; } - + /* create new stroke */ new_stroke = MEM_dupallocN(gps_from); new_stroke->points = MEM_dupallocN(gps_from->points); @@ -999,19 +999,19 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) new_stroke->tot_triangles = 0; new_stroke->flag |= GP_STROKE_RECALC_CACHES; } - + /* update points position */ gp_interpolate_update_points(gps_from, gps_to, new_stroke, factor); - + /* add to strokes */ BLI_addtail(&interFrame->strokes, new_stroke); } } } - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -1021,11 +1021,11 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot) ot->name = "Interpolate Sequence"; ot->idname = "GPENCIL_OT_interpolate_sequence"; ot->description = "Generate 'in-betweens' to smoothly interpolate between Grease Pencil frames"; - + /* api callbacks */ ot->exec = gpencil_interpolate_seq_exec; ot->poll = gpencil_view3d_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -1045,7 +1045,7 @@ static int gpencil_interpolate_reverse_poll(bContext *C) CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown"); return 0; } - + return 1; } @@ -1059,11 +1059,11 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op)) bGPDframe *start_key = NULL; bGPDframe *end_key = NULL; bGPDframe *gpf, *gpfn; - + /* Only continue if we're currently on a breakdown keyframe */ if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) continue; - + /* Search left for "start_key" (i.e. the first breakdown to remove) */ gpf = gpl->actframe; while (gpf) { @@ -1077,7 +1077,7 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op)) break; } } - + /* Search right for "end_key" (i.e. the last breakdown to remove) */ gpf = gpl->actframe; while (gpf) { @@ -1091,36 +1091,36 @@ static int gpencil_interpolate_reverse_exec(bContext *C, wmOperator *UNUSED(op)) break; } } - + /* Did we find anything? */ /* NOTE: We should only proceed if there's something before/after these extents... * Otherwise, there's just an extent of breakdowns with no keys to interpolate between */ - if ((start_key && end_key) && + if ((start_key && end_key) && ELEM(NULL, start_key->prev, end_key->next) == false) { /* Set actframe to the key before start_key, since the keys have been removed now */ gpl->actframe = start_key->prev; - + /* Free each frame we're removing (except the last one) */ for (gpf = start_key; gpf && gpf != end_key; gpf = gpfn) { gpfn = gpf->next; - + /* free strokes and their associated memory */ BKE_gpencil_free_strokes(gpf); BLI_freelinkN(&gpl->frames, gpf); } - + /* Now free the last one... */ BKE_gpencil_free_strokes(end_key); BLI_freelinkN(&gpl->frames, end_key); } } CTX_DATA_END; - + /* notifiers */ WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -1130,11 +1130,11 @@ void GPENCIL_OT_interpolate_reverse(wmOperatorType *ot) ot->name = "Remove Breakdowns"; ot->idname = "GPENCIL_OT_interpolate_reverse"; ot->description = "Remove breakdown frames generated by interpolating between two Grease Pencil frames"; - + /* callbacks */ ot->exec = gpencil_interpolate_reverse_exec; ot->poll = gpencil_interpolate_reverse_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 3a2169798e5..84a106856b3 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -57,28 +57,28 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil", 0, 0); wmKeyMapItem *kmi; - + /* Draw --------------------------------------- */ /* draw */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, 0, DKEY); RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW); RNA_boolean_set(kmi->ptr, "wait_for_input", false); - + /* draw - straight lines */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", LEFTMOUSE, KM_PRESS, KM_CTRL, DKEY); RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_STRAIGHT); RNA_boolean_set(kmi->ptr, "wait_for_input", false); - + /* draw - poly lines */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, KM_CTRL, DKEY); RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW_POLY); RNA_boolean_set(kmi->ptr, "wait_for_input", false); - + /* erase */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", RIGHTMOUSE, KM_PRESS, 0, DKEY); RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER); RNA_boolean_set(kmi->ptr, "wait_for_input", false); - + /* Tablet Mappings for Drawing ------------------ */ /* For now, only support direct drawing using the eraser, as most users using a tablet * may still want to use that as their primary pointing device! @@ -88,24 +88,24 @@ static void ed_keymap_gpencil_general(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_DRAW); RNA_boolean_set(kmi->ptr, "wait_for_input", false); #endif - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_draw", TABLET_ERASER, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "mode", GP_PAINTMODE_ERASER); RNA_boolean_set(kmi->ptr, "wait_for_input", false); - + /* Viewport Tools ------------------------------- */ - + /* Enter EditMode */ WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, DKEY); - + /* Pie Menu - For standard tools */ WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_tool_palette", QKEY, KM_PRESS, 0, DKEY); WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_settings_palette", WKEY, KM_PRESS, 0, DKEY); - + /* Add Blank Frame */ /* XXX: BKEY or NKEY? BKEY is easier to reach from DKEY, so we'll use that for now */ WM_keymap_add_item(keymap, "GPENCIL_OT_blank_frame_add", BKEY, KM_PRESS, 0, DKEY); - + /* Delete Active Frame - For easier video tutorials/review sessions */ /* NOTE: This works even when not in EditMode */ WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, 0, DKEY); @@ -125,81 +125,81 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) { wmKeyMap *keymap = WM_keymap_find(keyconf, "Grease Pencil Stroke Edit Mode", 0, 0); wmKeyMapItem *kmi; - + /* set poll callback - so that this keymap only gets enabled when stroke editmode is enabled */ keymap->poll = gp_stroke_editmode_poll; - + /* ----------------------------------------------- */ - + /* Exit EditMode */ WM_keymap_add_item(keymap, "GPENCIL_OT_editmode_toggle", TABKEY, KM_PRESS, 0, 0); - + /* Pie Menu - For settings/tools easy access */ WM_keymap_add_menu_pie(keymap, "GPENCIL_MT_pie_sculpt", EKEY, KM_PRESS, 0, DKEY); - + /* Brush Settings */ /* NOTE: We cannot expose these in the standard keymap, as they will interfere with regular hotkeys * in other modes. However, when we are dealing with Stroke Edit Mode, we know for certain * that the only data being edited is that of the Grease Pencil strokes */ - + /* CTRL + FKEY = Eraser Radius */ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0); RNA_string_set(kmi->ptr, "data_path_primary", "user_preferences.edit.grease_pencil_eraser_radius"); - + /* Interpolation */ WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate", EKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_interpolate_sequence", EKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); /* Sculpting ------------------------------------- */ - + /* Brush-Based Editing: - * EKEY + LMB = Single stroke, draw immediately + * EKEY + LMB = Single stroke, draw immediately * + Other Modifiers (Ctrl/Shift) = Invert, Smooth, etc. * * For the modal version, use D+E -> Sculpt */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, 0, EKEY); RNA_boolean_set(kmi->ptr, "wait_for_input", false); - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, EKEY); RNA_boolean_set(kmi->ptr, "wait_for_input", false); /*RNA_boolean_set(kmi->ptr, "use_invert", true);*/ - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_paint", LEFTMOUSE, KM_PRESS, KM_SHIFT, EKEY); RNA_boolean_set(kmi->ptr, "wait_for_input", false); /*RNA_boolean_set(kmi->ptr, "use_smooth", true);*/ - - + + /* Shift-FKEY = Sculpt Strength */ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.strength"); - + /* FKEY = Sculpt Brush Size */ kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0); RNA_string_set(kmi->ptr, "data_path_primary", "tool_settings.gpencil_sculpt.brush.size"); - - + + /* Selection ------------------------------------- */ /* select all */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", AKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "action", SEL_TOGGLE); - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_all", IKEY, KM_PRESS, KM_CTRL, 0); RNA_enum_set(kmi->ptr, "action", SEL_INVERT); - + /* circle select */ WM_keymap_add_item(keymap, "GPENCIL_OT_select_circle", CKEY, KM_PRESS, 0, 0); - + /* border select */ WM_keymap_add_item(keymap, "GPENCIL_OT_select_border", BKEY, KM_PRESS, 0, 0); - + /* lasso select */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "deselect", false); kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL, 0); RNA_boolean_set(kmi->ptr, "deselect", true); - + /* In the Node Editor, lasso select needs ALT modifier too (as somehow CTRL+LMB drag gets taken for "cut" quite early) * There probably isn't too much harm adding this for other editors too as part of standard GP editing keymap. This hotkey * combo doesn't seem to see much use under standard scenarios? @@ -208,57 +208,57 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "deselect", false); kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_SHIFT | KM_CTRL | KM_ALT, 0); RNA_boolean_set(kmi->ptr, "deselect", true); - + /* normal select */ WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "extend", true); RNA_boolean_set(kmi->ptr, "toggle", true); - + /* whole stroke select */ kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_select", SELECTMOUSE, KM_PRESS, KM_ALT, 0); RNA_boolean_set(kmi->ptr, "entire_strokes", true); - + /* select linked */ /* NOTE: While LKEY is redundant, not having it breaks the mode illusion too much */ WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_select_linked", LKEY, KM_PRESS, KM_CTRL, 0); - + /* select grouped */ WM_keymap_add_item(keymap, "GPENCIL_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0); - + /* select more/less */ WM_keymap_add_item(keymap, "GPENCIL_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0); - + /* Editing ----------------------------------------- */ - + /* duplicate and move selected points */ WM_keymap_add_item(keymap, "GPENCIL_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); - + /* delete */ WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", XKEY, KM_PRESS, 0, 0); WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_gpencil_delete", DELKEY, KM_PRESS, 0, 0); - + WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", XKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_dissolve", DELKEY, KM_PRESS, KM_CTRL, 0); - + WM_keymap_add_item(keymap, "GPENCIL_OT_active_frames_delete_all", XKEY, KM_PRESS, KM_SHIFT, 0); - + /* menu edit specials */ WM_keymap_add_menu(keymap, "GPENCIL_MT_gpencil_edit_specials", WKEY, KM_PRESS, 0, 0); /* join strokes */ WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL, 0); - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_stroke_join", JKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "type", GP_STROKE_JOINCOPY); - + /* copy + paste */ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0); - + #ifdef __APPLE__ WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0); @@ -266,32 +266,32 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) /* snap */ WM_keymap_add_menu(keymap, "GPENCIL_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0); - - + + /* convert to geometry */ WM_keymap_add_item(keymap, "GPENCIL_OT_convert", CKEY, KM_PRESS, KM_ALT, 0); - - + + /* Show/Hide */ /* NOTE: These are available only in EditMode now, since they clash with general-purpose hotkeys */ WM_keymap_add_item(keymap, "GPENCIL_OT_reveal", HKEY, KM_PRESS, KM_ALT, 0); - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "unselected", false); - + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "unselected", true); WM_keymap_add_item(keymap, "GPENCIL_OT_selection_opacity_toggle", HKEY, KM_PRESS, KM_CTRL, 0); - + /* Isolate Layer */ WM_keymap_add_item(keymap, "GPENCIL_OT_layer_isolate", PADASTERKEY, KM_PRESS, 0, 0); - + /* Move to Layer */ WM_keymap_add_item(keymap, "GPENCIL_OT_move_to_layer", MKEY, KM_PRESS, 0, 0); /* Select drawing brush using index */ - kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", ONEKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", ONEKEY, KM_PRESS, 0, 0); RNA_int_set(kmi->ptr, "index", 0); kmi = WM_keymap_add_item(keymap, "GPENCIL_OT_brush_select", TWOKEY, KM_PRESS, 0, 0); RNA_int_set(kmi->ptr, "index", 1); @@ -314,24 +314,24 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf) /* Transform Tools */ kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", GKEY, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_translate", EVT_TWEAK_S, KM_ANY, 0, 0); - + kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_rotate", RKEY, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_resize", SKEY, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0); - + kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_bend", WKEY, KM_PRESS, KM_SHIFT, 0); - + WM_keymap_add_item(keymap, "TRANSFORM_OT_tosphere", SKEY, KM_PRESS, KM_ALT | KM_SHIFT, 0); - + WM_keymap_add_item(keymap, "TRANSFORM_OT_shear", SKEY, KM_PRESS, KM_ALT | KM_CTRL | KM_SHIFT, 0); - + kmi = WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, KM_ALT, 0); RNA_enum_set(kmi->ptr, "mode", TFM_GPENCIL_SHRINKFATTEN); - + /* Proportional Editing */ ED_keymap_proportional_cycle(keyconf, keymap); ED_keymap_proportional_editmode(keyconf, keymap, true); @@ -350,11 +350,11 @@ void ED_keymap_gpencil(wmKeyConfig *keyconf) void ED_operatortypes_gpencil(void) { /* Drawing ----------------------- */ - + WM_operatortype_append(GPENCIL_OT_draw); - + /* Editing (Strokes) ------------ */ - + WM_operatortype_append(GPENCIL_OT_editmode_toggle); WM_operatortype_append(GPENCIL_OT_selection_opacity_toggle); @@ -363,41 +363,41 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_select_circle); WM_operatortype_append(GPENCIL_OT_select_border); WM_operatortype_append(GPENCIL_OT_select_lasso); - + WM_operatortype_append(GPENCIL_OT_select_linked); WM_operatortype_append(GPENCIL_OT_select_grouped); WM_operatortype_append(GPENCIL_OT_select_more); WM_operatortype_append(GPENCIL_OT_select_less); WM_operatortype_append(GPENCIL_OT_select_first); WM_operatortype_append(GPENCIL_OT_select_last); - + WM_operatortype_append(GPENCIL_OT_duplicate); WM_operatortype_append(GPENCIL_OT_delete); WM_operatortype_append(GPENCIL_OT_dissolve); WM_operatortype_append(GPENCIL_OT_copy); WM_operatortype_append(GPENCIL_OT_paste); - + WM_operatortype_append(GPENCIL_OT_move_to_layer); WM_operatortype_append(GPENCIL_OT_layer_change); - + WM_operatortype_append(GPENCIL_OT_snap_to_grid); WM_operatortype_append(GPENCIL_OT_snap_to_cursor); WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected); - + WM_operatortype_append(GPENCIL_OT_reproject); - + WM_operatortype_append(GPENCIL_OT_brush_paint); - + /* Editing (Buttons) ------------ */ - + WM_operatortype_append(GPENCIL_OT_data_add); WM_operatortype_append(GPENCIL_OT_data_unlink); - + WM_operatortype_append(GPENCIL_OT_layer_add); WM_operatortype_append(GPENCIL_OT_layer_remove); WM_operatortype_append(GPENCIL_OT_layer_move); WM_operatortype_append(GPENCIL_OT_layer_duplicate); - + WM_operatortype_append(GPENCIL_OT_hide); WM_operatortype_append(GPENCIL_OT_reveal); WM_operatortype_append(GPENCIL_OT_lock_all); @@ -406,10 +406,10 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_layer_merge); WM_operatortype_append(GPENCIL_OT_blank_frame_add); - + WM_operatortype_append(GPENCIL_OT_active_frame_delete); WM_operatortype_append(GPENCIL_OT_active_frames_delete_all); - + WM_operatortype_append(GPENCIL_OT_convert); WM_operatortype_append(GPENCIL_OT_stroke_arrange); @@ -445,7 +445,7 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_brush_select); /* Editing (Time) --------------- */ - + /* Interpolation */ WM_operatortype_append(GPENCIL_OT_interpolate); WM_operatortype_append(GPENCIL_OT_interpolate_sequence); @@ -456,7 +456,7 @@ void ED_operatormacros_gpencil(void) { wmOperatorType *ot; wmOperatorTypeMacro *otmacro; - + /* Duplicate + Move = Interactively place newly duplicated strokes */ ot = WM_operatortype_append_macro("GPENCIL_OT_duplicate_move", "Duplicate Strokes", "Make copies of the selected Grease Pencil strokes and move them", diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 84b3ddccf77..af140501069 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -112,35 +112,35 @@ typedef enum eGPencil_PaintFlags { */ typedef struct tGPsdata { Scene *scene; /* current scene from context */ - + wmWindow *win; /* window where painting originated */ ScrArea *sa; /* area where painting originated */ ARegion *ar; /* region where painting originated */ View2D *v2d; /* needed for GP_STROKE_2DSPACE */ rctf *subrect; /* for using the camera rect within the 3d view */ rctf subrect_data; - + GP_SpaceConversion gsc; /* settings to pass to gp_points_to_xy() */ - + PointerRNA ownerPtr; /* pointer to owner of gp-datablock */ bGPdata *gpd; /* gp-datablock layer comes from */ bGPDlayer *gpl; /* layer we're working on */ bGPDframe *gpf; /* frame we're working on */ - + char *align_flag; /* projection-mode flags (toolsettings - eGPencil_Placement_Flags) */ - + eGPencil_PaintStatus status; /* current status of painting */ eGPencil_PaintModes paintmode; /* mode for painting */ eGPencil_PaintFlags flags; /* flags that can get set during runtime (eGPencil_PaintFlags) */ - + short radius; /* radius of influence for eraser */ - + int mval[2]; /* current mouse-position */ int mvalo[2]; /* previous recorded mouse-position */ - + float pressure; /* current stylus pressure */ float opressure; /* previous stylus pressure */ - + /* These need to be doubles, as (at least under unix) they are in seconds since epoch, * float (and its 7 digits precision) is definitively not enough here! * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. @@ -148,13 +148,13 @@ typedef struct tGPsdata { double inittime; /* Used when converting to path */ double curtime; /* Used when converting to path */ double ocurtime; /* Used when converting to path */ - + float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space * to region space */ float mat[4][4]; - + float custom_color[4]; /* custom color - hack for enforcing a particular color for track/mask editing */ - + void *erasercursor; /* radial cursor data for drawing eraser */ bGPDpalettecolor *palettecolor; /* current palette color */ @@ -211,7 +211,7 @@ static int gpencil_draw_poll(bContext *C) else { CTX_wm_operator_poll_msg_set(C, "Active region not set"); } - + return 0; } @@ -232,12 +232,12 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) { View3D *v3d = p->sa->spacedata.first; const float *fp = ED_view3d_cursor3d_get(p->scene, v3d); - + /* the reference point used depends on the owner... */ #if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */ if (p->ownerPtr.type == &RNA_Object) { Object *ob = (Object *)p->ownerPtr.data; - + /* active Object * - use relative distance of 3D-cursor from object center */ @@ -258,24 +258,24 @@ static bool gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2]) { int dx = abs(mval[0] - pmval[0]); int dy = abs(mval[1] - pmval[1]); - + /* if buffer is empty, just let this go through (i.e. so that dots will work) */ if (p->gpd->sbuffer_size == 0) return true; - + /* check if mouse moved at least certain distance on both axes (best case) * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand */ else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) return true; - + /* check if the distance since the last point is significant enough * - prevents points being added too densely * - distance here doesn't use sqrt to prevent slowness... we should still be safe from overflows though */ else if ((dx * dx + dy * dy) > MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX) return true; - + /* mouse 'didn't move' */ else return false; @@ -344,7 +344,7 @@ static void gp_reproject_toplane(tGPsdata *p, bGPDstroke *gps) static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth) { bGPdata *gpd = p->gpd; - + /* in 3d-space - pt->x/y/z are 3 side-by-side floats */ if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) { if (gpencil_project_check(p) && (ED_view3d_autodist_simple(p->ar, mval, out, 0, depth))) { @@ -357,7 +357,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] float rvec[3], dvec[3]; float mval_f[2] = {UNPACK2(mval)}; float zfac; - + /* Current method just converts each point in screen-coordinates to * 3D-coordinates using the 3D-cursor as reference. In general, this * works OK, but it could of course be improved. @@ -366,10 +366,10 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] * - investigate using nearest point(s) on a previous stroke as * reference point instead or as offset, for easier stroke matching */ - + gp_get_3d_reference(p, rvec); zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL); - + if (ED_view3d_project_float_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { sub_v2_v2v2(mval_f, mval_prj, mval_f); ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac); @@ -380,13 +380,13 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] } } } - + /* 2d - on 'canvas' (assume that p->v2d is set) */ else if ((gpd->sbuffer_sflag & GP_STROKE_2DSPACE) && (p->v2d)) { UI_view2d_region_to_view(p->v2d, mval[0], mval[1], &out[0], &out[1]); mul_v3_m4v3(out, p->imat, out); } - + /* 2d - relative to screen (viewport area) */ else { if (p->subrect == NULL) { /* normal 3D view */ @@ -472,7 +472,7 @@ static void gp_brush_angle(bGPdata *gpd, bGPDbrush *brush, tGPspoint *pt, const fac = 1.0f - fabs(dot_v2v2(v0, mvec)); /* 0.0 to 1.0 */ /* interpolate with previous point for smoother transitions */ mpressure = interpf(pt->pressure - (sen * fac), (pt - 1)->pressure, 0.3f); - pt->pressure = mpressure; + pt->pressure = mpressure; CLAMP(pt->pressure, GPENCIL_ALPHA_OPACITY_THRESH, 1.0f); } @@ -493,13 +493,13 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, if (gpd->sbuffer_size == 0) { /* first point in buffer (start point) */ pt = (tGPspoint *)(gpd->sbuffer); - + /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); - + /* increment buffer size */ gpd->sbuffer_size++; } @@ -508,17 +508,17 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, * - assume that pointers for this are always valid... */ pt = ((tGPspoint *)(gpd->sbuffer) + 1); - + /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); - + /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ gpd->sbuffer_size = 2; } - + /* can keep carrying on this way :) */ return GP_STROKEADD_NORMAL; } @@ -526,10 +526,10 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, /* check if still room in buffer */ if (gpd->sbuffer_size >= GP_STROKE_BUFFER_MAX) return GP_STROKEADD_OVERFLOW; - + /* get pointer to destination point */ pt = ((tGPspoint *)(gpd->sbuffer) + gpd->sbuffer_size); - + /* store settings */ /* pressure */ if (brush->flag & GP_BRUSH_USE_PRESSURE) { @@ -591,10 +591,10 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, /* point time */ pt->time = (float)(curtime - p->inittime); - + /* increment counters */ gpd->sbuffer_size++; - + /* check if another operation can still occur */ if (gpd->sbuffer_size == GP_STROKE_BUFFER_MAX) return GP_STROKEADD_FULL; @@ -602,17 +602,17 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { - + bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); /* get pointer to destination point */ pt = (tGPspoint *)(gpd->sbuffer); - + /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = 1.0f; /* T44932 - Pressure vals are unreliable, so ignore for now */ pt->strength = 1.0f; pt->time = (float)(curtime - p->inittime); - + /* if there's stroke for this poly line session add (or replace last) point * to stroke. This allows to draw lines more interactively (see new segment * during mouse slide, e.g.) @@ -620,15 +620,15 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, if (gp_stroke_added_check(p)) { bGPDstroke *gps = p->gpf->strokes.last; bGPDspoint *pts; - + /* first time point is adding to temporary buffer -- need to allocate new point in stroke */ if (gpd->sbuffer_size == 0) { gps->points = MEM_reallocN(gps->points, sizeof(bGPDspoint) * (gps->totpoints + 1)); gps->totpoints++; } - + pts = &gps->points[gps->totpoints - 1]; - + /* special case for poly lines: normally, * depth is needed only when creating new stroke from buffer, * but poly lines are converting to stroke instantly, @@ -636,11 +636,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, */ if (gpencil_project_check(p)) { View3D *v3d = p->sa->spacedata.first; - + view3d_region_operator_needs_opengl(p->win, p->ar); ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } - + /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); /* if axis locked, reproject to plane locked (only in 3d space) */ @@ -658,11 +658,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, /* force fill recalc */ gps->flag |= GP_STROKE_RECALC_CACHES; } - + /* increment counters */ if (gpd->sbuffer_size == 0) gpd->sbuffer_size++; - + return GP_STROKEADD_NORMAL; } @@ -681,15 +681,15 @@ static void gp_stroke_simplify(tGPsdata *p) short num_points = gpd->sbuffer_size; short flag = gpd->sbuffer_sflag; short i, j; - + /* only simplify if simplification is enabled, and we're not doing a straight line */ if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)) return; - + /* don't simplify if less than 4 points in buffer */ if ((num_points <= 4) || (old_points == NULL)) return; - + /* clear buffer (but don't free mem yet) so that we can write to it * - firstly set sbuffer to NULL, so a new one is allocated * - secondly, reset flag after, as it gets cleared auto @@ -697,7 +697,7 @@ static void gp_stroke_simplify(tGPsdata *p) gpd->sbuffer = NULL; gp_session_validatebuffer(p); gpd->sbuffer_sflag = flag; - + /* macro used in loop to get position of new point * - used due to the mixture of datatypes in use here */ @@ -708,39 +708,39 @@ static void gp_stroke_simplify(tGPsdata *p) pressure += old_points[offs].pressure * sfac; \ time += old_points[offs].time * sfac; \ } (void)0 - + /* XXX Here too, do not lose start and end points! */ gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time); for (i = 0, j = 0; i < num_points; i++) { if (i - j == 3) { float co[2], pressure, time; int mco[2]; - + /* initialize values */ co[0] = 0.0f; co[1] = 0.0f; pressure = 0.0f; time = 0.0f; - + /* using macro, calculate new point */ GP_SIMPLIFY_AVPOINT(j, -0.25f); GP_SIMPLIFY_AVPOINT(j + 1, 0.75f); GP_SIMPLIFY_AVPOINT(j + 2, 0.75f); GP_SIMPLIFY_AVPOINT(j + 3, -0.25f); - + /* set values for adding */ mco[0] = (int)co[0]; mco[1] = (int)co[1]; - + /* ignore return values on this... assume to be ok for now */ gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time); - + j += 2; } } gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure, p->inittime + (double)old_points[num_points - 1].time); - + /* free old buffer */ MEM_freeN(old_points); } @@ -755,11 +755,11 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) tGPspoint *ptc; bGPDbrush *brush = p->brush; ToolSettings *ts = p->scene->toolsettings; - + int i, totelem; /* since strokes are so fine, when using their depth we need a margin otherwise they might get missed */ int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0; - + /* get total number of points to allocate space for * - drawing straight-lines only requires the endpoints */ @@ -767,14 +767,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) totelem = (gpd->sbuffer_size >= 2) ? 2 : gpd->sbuffer_size; else totelem = gpd->sbuffer_size; - + /* exit with error if no valid points from this stroke */ if (totelem == 0) { if (G.debug & G_DEBUG) printf("Error: No valid points in stroke buffer to convert (tot=%d)\n", gpd->sbuffer_size); return; } - + /* special case for poly line -- for already added stroke during session * coordinates are getting added to stroke immediately to allow more * interactive behavior @@ -784,23 +784,23 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) return; } } - + /* allocate memory for a new stroke */ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); - + /* copy appropriate settings for stroke */ gps->totpoints = totelem; gps->thickness = brush->thickness; gps->flag = gpd->sbuffer_sflag; gps->inittime = p->inittime; - + /* enable recalculation flag by default (only used if hq fill) */ gps->flag |= GP_STROKE_RECALC_CACHES; /* allocate enough memory for a continuous array for storage points */ int sublevel = brush->sublevel; int new_totpoints = gps->totpoints; - + for (i = 0; i < sublevel; i++) { new_totpoints += new_totpoints - 1; } @@ -811,14 +811,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->tot_triangles = 0; /* set pointer to first non-initialized point */ pt = gps->points + (gps->totpoints - totelem); - + /* copy points from the buffer to the stroke */ if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { /* straight lines only -> only endpoints */ { /* first point */ ptc = gpd->sbuffer; - + /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* if axis locked, reproject to plane locked (only in 3d space) */ @@ -834,14 +834,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = ptc->time; - + pt++; } - + if (totelem == 2) { /* last point if applicable */ ptc = ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1); - + /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* if axis locked, reproject to plane locked (only in 3d space) */ @@ -863,7 +863,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { /* first point */ ptc = gpd->sbuffer; - + /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); /* if axis locked, reproject to plane locked (only in 3d space) */ @@ -1005,7 +1005,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->palcolor = palcolor; BLI_strncpy(gps->colorname, palcolor->info, sizeof(gps->colorname)); - /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head + /* add stroke to frame, usually on tail of the listbase, but if on back is enabled the stroke is added on listbase head * because the drawing order is inverse and the head stroke is the first to draw. This is very useful for artist * when drawing the background */ @@ -1053,7 +1053,7 @@ static bool gp_stroke_eraser_is_occluded(tGPsdata *p, const bGPDspoint *pt, cons mul_v3_m4v3(fpt, diff_mat, &pt->x); const float depth_pt = view3d_point_depth(rv3d, fpt); - + if (depth_pt > depth_mval) { return true; } @@ -1068,13 +1068,13 @@ static float gp_stroke_eraser_calc_influence(tGPsdata *p, const int mval[2], con /* Linear Falloff... */ float distance = (float)len_v2v2_int(mval, co); float fac; - + CLAMP(distance, 0.0f, (float)radius); fac = 1.0f - (distance / (float)radius); - + /* Control this further using pen pressure */ fac *= p->pressure; - + /* Return influence factor computed here */ return fac; } @@ -1135,15 +1135,15 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, * below which we would have invisible strokes */ const float cull_thresh = (gps->thickness) ? 1.0f / ((float)gps->thickness) : 1.0f; - + /* Amount to decrease the pressure of each point with each stroke */ // TODO: Fetch from toolsettings, or compute based on thickness instead? const float strength = 0.1f; - + /* Perform culling? */ bool do_cull = false; - - + + /* Clear Tags * * Note: It's better this way, as we are sure that @@ -1154,7 +1154,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, bGPDspoint *pt = &gps->points[i]; pt->flag &= ~GP_SPOINT_TAG; } - + /* First Pass: Loop over the points in the stroke * 1) Thin out parts of the stroke under the brush * 2) Tag "too thin" parts for removal (in second pass) @@ -1167,7 +1167,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, /* only process if it hasn't been masked out... */ if ((p->flags & GP_PAINTFLAG_SELECTMASK) && !(gps->points->flag & GP_SPOINT_SELECT)) continue; - + if (gpl->parent == NULL) { gp_point_to_xy(&p->gsc, gps, pt1, &pc1[0], &pc1[1]); gp_point_to_xy(&p->gsc, gps, pt2, &pc2[0], &pc2[1]); @@ -1200,7 +1200,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, */ pt1->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc1) * strength; pt2->pressure -= gp_stroke_eraser_calc_influence(p, mval, radius, pc2) * strength / 2.0f; - + /* 2) Tag any point with overly low influence for removal in the next pass */ if (pt1->pressure < cull_thresh) { pt1->flag |= GP_SPOINT_TAG; @@ -1214,7 +1214,7 @@ static void gp_stroke_eraser_dostroke(tGPsdata *p, } } } - + /* Second Pass: Remove any points that are tagged */ if (do_cull) { gp_stroke_delete_tagged_points(gpf, gps, gps->next, GP_SPOINT_TAG); @@ -1228,29 +1228,29 @@ static void gp_stroke_doeraser(tGPsdata *p) bGPDlayer *gpl; bGPDstroke *gps, *gpn; rcti rect; - + /* rect is rectangle of eraser */ rect.xmin = p->mval[0] - p->radius; rect.ymin = p->mval[1] - p->radius; rect.xmax = p->mval[0] + p->radius; rect.ymax = p->mval[1] + p->radius; - + if (p->sa->spacetype == SPACE_VIEW3D) { if (p->flags & GP_PAINTFLAG_V3D_ERASER_DEPTH) { View3D *v3d = p->sa->spacedata.first; - + view3d_region_operator_needs_opengl(p->win, p->ar); ED_view3d_autodist_init(p->scene, p->ar, v3d, 0); } } - + /* loop over all layers too, since while it's easy to restrict editing to * only a subset of layers, it is harder to perform the same erase operation * on multiple layers... */ for (gpl = p->gpd->layers.first; gpl; gpl = gpl->next) { bGPDframe *gpf = gpl->actframe; - + /* only affect layer if it's editable (and visible) */ if (gpencil_layer_is_editable(gpl) == false) { continue; @@ -1258,7 +1258,7 @@ static void gp_stroke_doeraser(tGPsdata *p) else if (gpf == NULL) { continue; } - + /* loop over strokes, checking segments for intersections */ for (gps = gpf->strokes.first; gps; gps = gpn) { gpn = gps->next; @@ -1283,7 +1283,7 @@ static void gp_stroke_doeraser(tGPsdata *p) static void gp_session_validatebuffer(tGPsdata *p) { bGPdata *gpd = p->gpd; - + /* clear memory of buffer (or allocate it if starting a new session) */ if (gpd->sbuffer) { /* printf("\t\tGP - reset sbuffer\n"); */ @@ -1293,13 +1293,13 @@ static void gp_session_validatebuffer(tGPsdata *p) /* printf("\t\tGP - allocate sbuffer\n"); */ gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); } - + /* reset indices */ gpd->sbuffer_size = 0; - + /* reset flags */ gpd->sbuffer_sflag = 0; - + /* reset inittime */ p->inittime = 0.0; } @@ -1310,7 +1310,7 @@ static bGPDpalettecolor *gp_create_new_color(bGPDpalette *palette) bGPDpalettecolor *palcolor; palcolor = BKE_gpencil_palettecolor_addnew(palette, DATA_("Color"), true); - + return palcolor; } @@ -1383,7 +1383,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) ScrArea *curarea = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); ToolSettings *ts = CTX_data_tool_settings(C); - + /* make sure the active view (at the starting time) is a 3d-view */ if (curarea == NULL) { p->status = GP_STATUS_ERROR; @@ -1391,21 +1391,21 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) printf("Error: No active view for painting\n"); return 0; } - + /* pass on current scene and window */ p->scene = CTX_data_scene(C); p->win = CTX_wm_window(C); - + unit_m4(p->imat); unit_m4(p->mat); - + switch (curarea->spacetype) { /* supported views first */ case SPACE_VIEW3D: { /* View3D *v3d = curarea->spacedata.first; */ /* RegionView3D *rv3d = ar->regiondata; */ - + /* set current area * - must verify that region data is 3D-view (and not something else) */ @@ -1413,7 +1413,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) p->sa = curarea; p->ar = ar; p->align_flag = &ts->gpencil_v3d_align; - + if (ar->regiondata == NULL) { p->status = GP_STATUS_ERROR; if (G.debug & G_DEBUG) @@ -1425,7 +1425,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) case SPACE_NODE: { /* SpaceNode *snode = curarea->spacedata.first; */ - + /* set current area */ p->sa = curarea; p->ar = ar; @@ -1436,13 +1436,13 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) case SPACE_SEQ: { SpaceSeq *sseq = curarea->spacedata.first; - + /* set current area */ p->sa = curarea; p->ar = ar; p->v2d = &ar->v2d; p->align_flag = &ts->gpencil_seq_align; - + /* check that gpencil data is allowed to be drawn */ if (sseq->mainb == SEQ_DRAW_SEQUENCE) { p->status = GP_STATUS_ERROR; @@ -1455,7 +1455,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) case SPACE_IMAGE: { /* SpaceImage *sima = curarea->spacedata.first; */ - + /* set the current area */ p->sa = curarea; p->ar = ar; @@ -1467,7 +1467,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) { SpaceClip *sc = curarea->spacedata.first; MovieClip *clip = ED_space_clip_get_clip(sc); - + if (clip == NULL) { p->status = GP_STATUS_ERROR; return false; @@ -1478,15 +1478,15 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) p->ar = ar; p->v2d = &ar->v2d; p->align_flag = &ts->gpencil_v2d_align; - + invert_m4_m4(p->imat, sc->unistabmat); - + /* custom color for new layer */ p->custom_color[0] = 1.0f; p->custom_color[1] = 0.0f; p->custom_color[2] = 0.5f; p->custom_color[3] = 0.9f; - + if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { int framenr = ED_space_clip_get_clip_frame_number(sc); MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); @@ -1501,7 +1501,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) return false; } } - + invert_m4_m4(p->mat, p->imat); copy_m4_m4(p->gsc.mat, p->mat); break; @@ -1515,7 +1515,7 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) return 0; } } - + /* get gp-data */ gpd_ptr = ED_gpencil_data_get_pointers(C, &p->ownerPtr); if (gpd_ptr == NULL) { @@ -1530,14 +1530,14 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) *gpd_ptr = BKE_gpencil_data_addnew("GPencil"); p->gpd = *gpd_ptr; } - + if (ED_gpencil_session_active() == 0) { /* initialize undo stack, * also, existing undo stack would make buffer drawn */ gpencil_undo_init(p->gpd); } - + /* clear out buffer (stored in gp-data), in case something contaminated it */ gp_session_validatebuffer(p); /* set brush and create a new one if null */ @@ -1559,12 +1559,12 @@ static bool gp_session_initdata(bContext *C, tGPsdata *p) static tGPsdata *gp_session_initpaint(bContext *C) { tGPsdata *p = NULL; - + /* create new context data */ p = MEM_callocN(sizeof(tGPsdata), "GPencil Drawing Data"); - + gp_session_initdata(C, p); - + /* radius for eraser circle is defined in userprefs now */ /* NOTE: we do this here, so that if we exit immediately, * erase size won't get lost @@ -1579,18 +1579,18 @@ static tGPsdata *gp_session_initpaint(bContext *C) static void gp_session_cleanup(tGPsdata *p) { bGPdata *gpd = (p) ? p->gpd : NULL; - + /* error checking */ if (gpd == NULL) return; - + /* free stroke buffer */ if (gpd->sbuffer) { /* printf("\t\tGP - free sbuffer\n"); */ MEM_freeN(gpd->sbuffer); gpd->sbuffer = NULL; } - + /* clear flags */ gpd->sbuffer_size = 0; gpd->sbuffer_sflag = 0; @@ -1602,12 +1602,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) { Scene *scene = p->scene; ToolSettings *ts = scene->toolsettings; - + /* get active layer (or add a new one if non-existent) */ p->gpl = BKE_gpencil_layer_getactive(p->gpd); if (p->gpl == NULL) { p->gpl = BKE_gpencil_layer_addnew(p->gpd, "GP_Layer", true); - + if (p->custom_color[3]) copy_v3_v3(p->gpl->color, p->custom_color); } @@ -1617,7 +1617,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) printf("Error: Cannot paint on locked layer\n"); return; } - + /* get active frame (add a new one if not matching frame) */ if (paintmode == GP_PAINTMODE_ERASER) { /* Eraser mode: @@ -1626,12 +1626,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) * (to avoid problems with other tools which expect it to exist) */ bool has_layer_to_erase = false; - + for (bGPDlayer *gpl = p->gpd->layers.first; gpl; gpl = gpl->next) { /* Skip if layer not editable */ if (gpencil_layer_is_editable(gpl) == false) continue; - + /* Add a new frame if needed (and based off the active frame, * as we need some existing strokes to erase) * @@ -1643,16 +1643,16 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) gpl->actframe = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY); has_layer_to_erase = true; } - + /* XXX: we omit GP_FRAME_PAINT here for now, * as it is only really useful for doing * paintbuffer drawing */ } - + /* Ensure this gets set... */ p->gpf = p->gpl->actframe; - + /* Restrict eraser to only affecting selected strokes, if the "selection mask" is on * (though this is only available in editmode) */ @@ -1661,7 +1661,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) p->flags |= GP_PAINTFLAG_SELECTMASK; } } - + if (has_layer_to_erase == false) { p->status = GP_STATUS_ERROR; //if (G.debug & G_DEBUG) @@ -1672,14 +1672,14 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) else { /* Drawing Modes - Add a new frame if needed on the active layer */ short add_frame_mode; - + if (ts->gpencil_flags & GP_TOOL_FLAG_RETAIN_LAST) add_frame_mode = GP_GETFRAME_ADD_COPY; else add_frame_mode = GP_GETFRAME_ADD_NEW; - + p->gpf = BKE_gpencil_layer_getframe(p->gpl, CFRA, add_frame_mode); - + if (p->gpf == NULL) { p->status = GP_STATUS_ERROR; if (G.debug & G_DEBUG) @@ -1690,12 +1690,12 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) p->gpf->flag |= GP_FRAME_PAINT; } } - + /* set 'eraser' for this stroke if using eraser */ p->paintmode = paintmode; if (p->paintmode == GP_PAINTMODE_ERASER) { p->gpd->sbuffer_sflag |= GP_STROKE_ERASER; - + /* check if we should respect depth while erasing */ if (p->sa->spacetype == SPACE_VIEW3D) { if (p->gpl->flag & GP_LAYER_NO_XRAY) { @@ -1706,25 +1706,25 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) else { /* disable eraser flags - so that we can switch modes during a session */ p->gpd->sbuffer_sflag &= ~GP_STROKE_ERASER; - + if (p->sa->spacetype == SPACE_VIEW3D) { if (p->gpl->flag & GP_LAYER_NO_XRAY) { p->flags &= ~GP_PAINTFLAG_V3D_ERASER_DEPTH; } } } - + /* set 'initial run' flag, which is only used to denote when a new stroke is starting */ p->flags |= GP_PAINTFLAG_FIRSTRUN; - - + + /* when drawing in the camera view, in 2D space, set the subrect */ p->subrect = NULL; if ((*p->align_flag & GP_PROJECT_VIEWSPACE) == 0) { if (p->sa->spacetype == SPACE_VIEW3D) { View3D *v3d = p->sa->spacedata.first; RegionView3D *rv3d = p->ar->regiondata; - + /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { ED_view3d_calc_camera_border(p->scene, p->ar, v3d, rv3d, &p->subrect_data, true); /* no shift */ @@ -1732,21 +1732,21 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) } } } - + /* init stroke point space-conversion settings... */ p->gsc.gpd = p->gpd; p->gsc.gpl = p->gpl; - + p->gsc.sa = p->sa; p->gsc.ar = p->ar; p->gsc.v2d = p->v2d; - + p->gsc.subrect_data = p->subrect_data; p->gsc.subrect = p->subrect; - + copy_m4_m4(p->gsc.mat, p->mat); - - + + /* check if points will need to be made in view-aligned space */ if (*p->align_flag & GP_PROJECT_VIEWSPACE) { switch (p->sa->spacetype) { @@ -1768,7 +1768,7 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode) case SPACE_IMAGE: { SpaceImage *sima = (SpaceImage *)p->sa->spacedata.first; - + /* only set these flags if the image editor doesn't have an image active, * otherwise user will be confused by strokes not appearing after they're drawn * @@ -1802,21 +1802,21 @@ static void gp_paint_strokeend(tGPsdata *p) */ if (gpencil_project_check(p)) { View3D *v3d = p->sa->spacedata.first; - + /* need to restore the original projection settings before packing up */ view3d_region_operator_needs_opengl(p->win, p->ar); ED_view3d_autodist_init(p->scene, p->ar, v3d, (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 1 : 0); } - + /* check if doing eraser or not */ if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* simplify stroke before transferring? */ gp_stroke_simplify(p); - + /* transfer stroke to frame */ gp_stroke_newfrombuffer(p); } - + /* clean up buffer now */ gp_session_validatebuffer(p); } @@ -1831,7 +1831,7 @@ static void gp_paint_cleanup(tGPsdata *p) /* finish off a stroke */ gp_paint_strokeend(p); } - + /* "unlock" frame */ if (p->gpf) p->gpf->flag &= ~GP_FRAME_PAINT; @@ -1843,27 +1843,27 @@ static void gp_paint_cleanup(tGPsdata *p) static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) { tGPsdata *p = (tGPsdata *)p_ptr; - + if (p->paintmode == GP_PAINTMODE_ERASER) { glPushMatrix(); - + glTranslatef((float)x, (float)y, 0.0f); - + glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); - + glColor4ub(255, 100, 100, 20); glutil_draw_filled_arc(0.0, M_PI * 2.0, p->radius, 40); - + setlinestyle(6); - + glColor4ub(255, 100, 100, 200); glutil_draw_lined_arc(0.0, M_PI * 2.0, p->radius, 40); - + setlinestyle(0); glDisable(GL_BLEND); glDisable(GL_LINE_SMOOTH); - + glPopMatrix(); } } @@ -1891,7 +1891,7 @@ static bool gpencil_is_tablet_eraser_active(const wmEvent *event) const wmTabletData *wmtab = event->tablet_data; return (wmtab->Active == EVT_TABLET_ERASER); } - + return false; } @@ -1900,13 +1900,13 @@ static bool gpencil_is_tablet_eraser_active(const wmEvent *event) static void gpencil_draw_exit(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; - + /* clear undo stack */ gpencil_undo_finish(); - + /* restore cursor to indicate end of drawing */ WM_cursor_modal_restore(CTX_wm_window(C)); - + /* don't assume that operator data exists at all */ if (p) { /* check size of buffer before cleanup, to determine if anything happened here */ @@ -1920,15 +1920,15 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) * have been toggled at some point. */ U.gp_eraser = p->radius; - + /* cleanup */ gp_paint_cleanup(p); gp_session_cleanup(p); - + /* finally, free the temp data */ MEM_freeN(p); } - + op->customdata = NULL; } @@ -1945,7 +1945,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p; eGPencil_PaintModes paintmode = RNA_enum_get(op->ptr, "mode"); - + /* check context */ p = op->customdata = gp_session_initpaint(C); if ((p == NULL) || (p->status == GP_STATUS_ERROR)) { @@ -1953,7 +1953,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) gpencil_draw_exit(C, op); return 0; } - + /* init painting data */ gp_paint_initstroke(p, paintmode); if (p->status == GP_STATUS_ERROR) { @@ -1967,7 +1967,7 @@ static int gpencil_draw_init(bContext *C, wmOperator *op, const wmEvent *event) else { p->keymodifier = -1; } - + /* everything is now setup ok */ return 1; } @@ -1994,7 +1994,7 @@ static void gpencil_draw_status_indicators(tGPsdata *p) if (GPENCIL_SKETCH_SESSIONS_ON(p->scene)) ED_area_headerprint(p->sa, IFACE_("Grease Pencil: Drawing/erasing stroke... Release to end stroke")); break; - + case GP_STATUS_IDLING: /* print status info */ switch (p->paintmode) { @@ -2014,13 +2014,13 @@ static void gpencil_draw_status_indicators(tGPsdata *p) ED_area_headerprint(p->sa, IFACE_("Grease Pencil Poly Session: LMB click to place next stroke vertex | " "ESC/Enter to end (or click outside this area)")); break; - + default: /* unhandled future cases */ ED_area_headerprint(p->sa, IFACE_("Grease Pencil Session: ESC/Enter to end (or click outside this area)")); break; } break; - + case GP_STATUS_ERROR: case GP_STATUS_DONE: /* clear status string */ @@ -2038,7 +2038,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) if (p->paintmode == GP_PAINTMODE_ERASER) { /* do 'live' erasing now */ gp_stroke_doeraser(p); - + /* store used values */ p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; @@ -2048,14 +2048,14 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { /* try to add point */ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); - + /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ gp_paint_strokeend(p); /* And start a new one!!! Else, projection errors! */ gp_paint_initstroke(p, p->paintmode); - + /* start a new stroke, starting from previous point */ /* XXX Must manually reset inittime... */ /* XXX We only need to reuse previous point if overflow! */ @@ -2072,12 +2072,12 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) /* the painting operation cannot continue... */ BKE_report(op->reports, RPT_ERROR, "Cannot paint stroke"); p->status = GP_STATUS_ERROR; - + if (G.debug & G_DEBUG) printf("Error: Grease-Pencil Paint - Add Point Invalid\n"); return; } - + /* store used values */ p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; @@ -2093,13 +2093,13 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) PointerRNA itemptr; float mousef[2]; int tablet = 0; - + /* convert from window-space to area-space mouse coordinates * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... */ p->mval[0] = event->mval[0] + 1; p->mval[1] = event->mval[1] + 1; - + /* verify key status for straight lines */ if ((event->ctrl > 0) || (event->alt > 0)) { if (p->straight[0] == 0) { @@ -2125,14 +2125,14 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) } p->curtime = PIL_check_seconds_timer(); - + /* handle pressure sensitivity (which is supplied by tablets) */ if (event->tablet_data) { const wmTabletData *wmtab = event->tablet_data; - + tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; - + /* Hack for pressure sensitive eraser on D+RMB when using a tablet: * The pen has to float over the tablet surface, resulting in * zero pressure (T47101). Ignore pressure values if floating @@ -2149,11 +2149,11 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) /* No tablet data -> No pressure info is available */ p->pressure = 1.0f; } - + /* special exception for start of strokes (i.e. maybe for just a dot) */ if (p->flags & GP_PAINTFLAG_FIRSTRUN) { p->flags &= ~GP_PAINTFLAG_FIRSTRUN; - + p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; @@ -2167,7 +2167,7 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) if (tablet && (p->pressure >= 0.99f)) return; } - + /* check if alt key is pressed and limit to straight lines */ if (p->straight[0] != 0) { if (p->straight[0] == 1) { @@ -2182,18 +2182,18 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) /* fill in stroke data (not actually used directly by gpencil_draw_apply) */ RNA_collection_add(op->ptr, "stroke", &itemptr); - + mousef[0] = p->mval[0]; mousef[1] = p->mval[1]; RNA_float_set_array(&itemptr, "mouse", mousef); RNA_float_set(&itemptr, "pressure", p->pressure); RNA_boolean_set(&itemptr, "is_start", (p->flags & GP_PAINTFLAG_FIRSTRUN) != 0); - + RNA_float_set(&itemptr, "time", p->curtime - p->inittime); - + /* apply the current latest drawing point */ gpencil_draw_apply(op, p); - + /* force refresh */ ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */ } @@ -2204,9 +2204,9 @@ static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) static int gpencil_draw_exec(bContext *C, wmOperator *op) { tGPsdata *p = NULL; - + /* printf("GPencil - Starting Re-Drawing\n"); */ - + /* try to initialize context data needed while drawing */ if (!gpencil_draw_init(C, op, NULL)) { if (op->customdata) MEM_freeN(op->customdata); @@ -2215,25 +2215,25 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) } else p = op->customdata; - + /* printf("\tGP - Start redrawing stroke\n"); */ - + /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), * setting the relevant values in context at each step, then applying */ RNA_BEGIN (op->ptr, itemptr, "stroke") { float mousef[2]; - + /* printf("\t\tGP - stroke elem\n"); */ - + /* get relevant data for this point from stroke */ RNA_float_get_array(&itemptr, "mouse", mousef); p->mval[0] = (int)mousef[0]; p->mval[1] = (int)mousef[1]; p->pressure = RNA_float_get(&itemptr, "pressure"); p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime; - + if (RNA_boolean_get(&itemptr, "is_start")) { /* if first-run flag isn't set already (i.e. not true first stroke), * then we must terminate the previous one first before continuing @@ -2244,30 +2244,30 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) gp_paint_initstroke(p, p->paintmode); } } - + /* if first run, set previous data too */ if (p->flags & GP_PAINTFLAG_FIRSTRUN) { p->flags &= ~GP_PAINTFLAG_FIRSTRUN; - + p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; p->ocurtime = p->curtime; } - + /* apply this data as necessary now (as per usual) */ gpencil_draw_apply(op, p); } RNA_END; - + /* printf("\tGP - done\n"); */ - + /* cleanup */ gpencil_draw_exit(C, op); - + /* refreshes */ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); - + /* done */ return OPERATOR_FINISHED; } @@ -2278,10 +2278,10 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = NULL; - + if (G.debug & G_DEBUG) printf("GPencil - Starting Drawing\n"); - + /* try to initialize context data needed while drawing */ if (!gpencil_draw_init(C, op, event)) { if (op->customdata) @@ -2292,17 +2292,17 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event } else p = op->customdata; - + /* TODO: set any additional settings that we can take from the events? * TODO? if tablet is erasing, force eraser to be on? */ - + /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */ - + /* if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { gpencil_draw_toggle_eraser_cursor(C, p, true); } - /* set cursor + /* set cursor * NOTE: This may change later (i.e. intentionally via brush toggle, * or unintentionally if the user scrolls outside the area)... */ @@ -2323,7 +2323,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ op->flag |= OP_IS_MODAL_CURSOR_REGION; } - + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); /* add a modal handler for this operator, so that we can then draw continuous strokes */ WM_event_add_modal_handler(C, op); @@ -2340,7 +2340,7 @@ static bool gpencil_area_exists(bContext *C, ScrArea *sa_test) static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) { tGPsdata *p = op->customdata; - + /* we must check that we're still within the area that we're set up to work from * otherwise we could crash (see bug #20586) */ @@ -2348,37 +2348,37 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) printf("\t\t\tGP - wrong area execution abort!\n"); p->status = GP_STATUS_ERROR; } - + /* printf("\t\tGP - start stroke\n"); */ - + /* we may need to set up paint env again if we're resuming */ /* XXX: watch it with the paintmode! in future, * it'd be nice to allow changing paint-mode when in sketching-sessions */ - + if (gp_session_initdata(C, p)) gp_paint_initstroke(p, p->paintmode); - + if (p->status != GP_STATUS_ERROR) { p->status = GP_STATUS_PAINTING; op->flag &= ~OP_IS_MODAL_CURSOR_REGION; } - + return op->customdata; } static void gpencil_stroke_end(wmOperator *op) { tGPsdata *p = op->customdata; - + gp_paint_cleanup(p); - + gpencil_undo_push(p->gpd); - + gp_session_cleanup(p); - + p->status = GP_STATUS_IDLING; op->flag |= OP_IS_MODAL_CURSOR_REGION; - + p->gpd = NULL; p->gpl = NULL; p->gpf = NULL; @@ -2412,7 +2412,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) tGPsdata *p = op->customdata; ToolSettings *ts = CTX_data_tool_settings(C); int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */ - + /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; * ------------------------------- @@ -2425,7 +2425,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * better in tools that immediately apply * in 3D space. */ - + if (p->status == GP_STATUS_IDLING) { ARegion *ar = CTX_wm_region(C); p->ar = ar; @@ -2462,9 +2462,9 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_RUNNING_MODAL; } } - + //printf("\tGP - handle modal event...\n"); - + /* exit painting mode (and/or end current stroke) * NOTE: cannot do RIGHTMOUSE (as is standard for canceling) as that would break polyline [#32647] */ @@ -2482,7 +2482,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } - + /* toggle painting mode upon mouse-button movement * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only) * - RIGHTMOUSE = polyline (hotkey) / eraser (all) @@ -2493,31 +2493,31 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* if painting, end stroke */ if (p->status == GP_STATUS_PAINTING) { int sketch = 0; - + /* basically, this should be mouse-button up = end stroke * BUT what happens next depends on whether we 'painting sessions' is enabled */ sketch |= GPENCIL_SKETCH_SESSIONS_ON(p->scene); /* polyline drawing is also 'sketching' -- all knots should be added during one session */ sketch |= (p->paintmode == GP_PAINTMODE_DRAW_POLY); - + if (sketch) { /* end stroke only, and then wait to resume painting soon */ /* printf("\t\tGP - end stroke only\n"); */ gpencil_stroke_end(op); - + /* If eraser mode is on, turn it off after the stroke finishes * NOTE: This just makes it nicer to work with drawing sessions */ if (p->paintmode == GP_PAINTMODE_ERASER) { p->paintmode = RNA_enum_get(op->ptr, "mode"); - + /* if the original mode was *still* eraser, * we'll let it say for now, since this gives * users an opportunity to have visual feedback * when adjusting eraser size */ - if (p->paintmode != GP_PAINTMODE_ERASER) { + if (p->paintmode != GP_PAINTMODE_ERASER) { /* turn off cursor... * NOTE: this should be enough for now * Just hiding this makes it seem like @@ -2526,10 +2526,10 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_draw_toggle_eraser_cursor(C, p, false); } } - + /* we've just entered idling state, so this event was processed (but no others yet) */ estate = OPERATOR_RUNNING_MODAL; - + /* stroke could be smoothed, send notifier to refresh screen */ WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } @@ -2549,7 +2549,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } else if (event->val == KM_PRESS) { bool in_bounds = false; - + /* Check if we're outside the bounds of the active region * NOTE: An exception here is that if launched from the toolbar, * whatever region we're now in should become the new region @@ -2557,13 +2557,13 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) if ((p->ar) && (p->ar->regiontype == RGN_TYPE_TOOLS)) { /* Change to whatever region is now under the mouse */ ARegion *current_region = BKE_area_find_region_xy(p->sa, RGN_TYPE_ANY, event->x, event->y); - + if (G.debug & G_DEBUG) { printf("found alternative region %p (old was %p) - at %d %d (sa: %d %d -> %d %d)\n", current_region, p->ar, event->x, event->y, p->sa->totrct.xmin, p->sa->totrct.ymin, p->sa->totrct.xmax, p->sa->totrct.ymax); } - + if (current_region) { /* Assume that since we found the cursor in here, it is in bounds * and that this should be the region that we begin drawing in @@ -2575,14 +2575,14 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* Out of bounds, or invalid in some other way */ p->status = GP_STATUS_ERROR; estate = OPERATOR_CANCELLED; - + if (G.debug & G_DEBUG) printf("%s: Region under cursor is out of bounds, so cannot be drawn on\n", __func__); } } else if (p->ar) { rcti region_rect; - + /* Perform bounds check using */ ED_region_visible_rect(p->ar, ®ion_rect); in_bounds = BLI_rcti_isect_pt_v(®ion_rect, event->mval); @@ -2591,11 +2591,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* No region */ p->status = GP_STATUS_ERROR; estate = OPERATOR_CANCELLED; - + if (G.debug & G_DEBUG) printf("%s: No active region found in GP Paint session data\n", __func__); } - + if (in_bounds) { /* Switch paintmode (temporarily if need be) based on which button was used * NOTE: This is to make it more convenient to erase strokes when using drawing sessions @@ -2608,18 +2608,18 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* restore drawmode to default */ p->paintmode = RNA_enum_get(op->ptr, "mode"); } - + gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); - + /* not painting, so start stroke (this should be mouse-button down) */ p = gpencil_stroke_begin(C, op); - + if (p->status == GP_STATUS_ERROR) { estate = OPERATOR_CANCELLED; } } else if (p->status != GP_STATUS_ERROR) { - /* User clicked outside bounds of window while idling, so exit paintmode + /* User clicked outside bounds of window while idling, so exit paintmode * NOTE: Don't enter this case if an error occurred while finding the * region (as above) */ @@ -2640,7 +2640,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) op->flag |= OP_IS_MODAL_CURSOR_REGION; } } - + /* handle mode-specific events */ if (p->status == GP_STATUS_PAINTING) { /* handle painting mouse-movements? */ @@ -2648,7 +2648,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) /* handle drawing event */ /* printf("\t\tGP - add point\n"); */ gpencil_draw_apply_event(op, event); - + /* finish painting operation if anything went wrong just now */ if (p->status == GP_STATUS_ERROR) { printf("\t\t\t\tGP - add error done!\n"); @@ -2673,19 +2673,19 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) case PADPLUSKEY: p->radius += 5; break; - + case WHEELUPMOUSE: /* smaller */ case PADMINUS: p->radius -= 5; - + if (p->radius <= 0) p->radius = 1; break; } - + /* force refresh */ ED_region_tag_redraw(p->ar); /* just active area for now, since doing whole screen is too slow */ - + /* event handled, so just tag as running modal */ estate = OPERATOR_RUNNING_MODAL; } @@ -2697,7 +2697,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_RUNNING_MODAL; } } - + /* gpencil modal operator stores area, which can be removed while using it (like fullscreen) */ if (0 == gpencil_area_exists(C, p->sa)) estate = OPERATOR_CANCELLED; @@ -2706,7 +2706,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_draw_status_indicators(p); gpencil_draw_cursor_set(p); /* cursor may have changed outside our control - T44084 */ } - + /* process last operations before exiting */ switch (estate) { case OPERATOR_FINISHED: @@ -2714,11 +2714,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_draw_exit(C, op); WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); break; - + case OPERATOR_CANCELLED: gpencil_draw_exit(C, op); break; - + case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH: /* event doesn't need to be handled */ #if 0 @@ -2727,7 +2727,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) #endif break; } - + /* return status code */ return estate; } @@ -2745,28 +2745,28 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = { void GPENCIL_OT_draw(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Grease Pencil Draw"; ot->idname = "GPENCIL_OT_draw"; ot->description = "Make annotations on the active data"; - + /* api callbacks */ ot->exec = gpencil_draw_exec; ot->invoke = gpencil_draw_invoke; ot->modal = gpencil_draw_modal; ot->cancel = gpencil_draw_cancel; ot->poll = gpencil_draw_poll; - + /* flags */ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; - + /* settings for drawing */ ot->prop = RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); - + /* NOTE: wait for input is enabled by default, so that all UI code can work properly without needing users to know about this */ prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "Wait for first click instead of painting immediately"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index dc3483163bf..ac0b046e499 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -70,14 +70,14 @@ static int gpencil_select_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + /* we just need some visible strokes, and to be in editmode */ if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) { /* TODO: include a check for visible strokes? */ if (gpd->layers.first) return true; } - + return false; } @@ -88,16 +88,16 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); int action = RNA_enum_get(op->ptr, "action"); - + if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); return OPERATOR_CANCELLED; } - + /* for "toggle", test for existing selected strokes */ if (action == SEL_TOGGLE) { action = SEL_SELECT; - + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { if (gps->flag & GP_STROKE_SELECT) { @@ -107,7 +107,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) } CTX_DATA_END; } - + /* if deselecting, we need to deselect strokes across all frames * - Currently, an exception is only given for deselection * Selecting and toggling should only affect what's visible, @@ -122,21 +122,21 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf; - + /* deselect all strokes on all frames */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { bGPDstroke *gps; - + for (gps = gpf->strokes.first; gps; gps = gps->next) { bGPDspoint *pt; int i; - + /* only edit strokes that are valid in this view... */ if (ED_gpencil_stroke_can_use(C, gps)) { for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } - + gps->flag &= ~GP_STROKE_SELECT; } } @@ -151,7 +151,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) bGPDspoint *pt; int i; bool selected = false; - + /* Change selection status of all points, then make the stroke match */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { switch (action) { @@ -165,11 +165,11 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) pt->flag ^= GP_SPOINT_SELECT; break; } - + if (pt->flag & GP_SPOINT_SELECT) selected = true; } - + /* Change status of stroke */ if (selected) gps->flag |= GP_STROKE_SELECT; @@ -178,7 +178,7 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op) } CTX_DATA_END; } - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -190,14 +190,14 @@ void GPENCIL_OT_select_all(wmOperatorType *ot) ot->name = "(De)select All Strokes"; ot->idname = "GPENCIL_OT_select_all"; ot->description = "Change selection of all Grease Pencil strokes currently visible"; - + /* callbacks */ ot->exec = gpencil_select_all_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + WM_operator_properties_select_all(ot); } @@ -207,26 +207,26 @@ void GPENCIL_OT_select_all(wmOperatorType *ot) static int gpencil_select_linked_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); - + if (gpd == NULL) { BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data"); return OPERATOR_CANCELLED; } - + /* select all points in selected strokes */ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag |= GP_SPOINT_SELECT; } } } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -238,11 +238,11 @@ void GPENCIL_OT_select_linked(wmOperatorType *ot) ot->name = "Select Linked"; ot->idname = "GPENCIL_OT_select_linked"; ot->description = "Select all points in same strokes as already selected points"; - + /* callbacks */ ot->exec = gpencil_select_linked_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -253,10 +253,10 @@ void GPENCIL_OT_select_linked(wmOperatorType *ot) typedef enum eGP_SelectGrouped { /* Select strokes in the same layer */ GP_SEL_SAME_LAYER = 0, - + /* Select strokes with the same color */ GP_SEL_SAME_COLOR = 1, - + /* TODO: All with same prefix - Useful for isolating all layers for a particular character for instance */ /* TODO: All with same appearance - colour/opacity/volumetric/fills ? */ } eGP_SelectGrouped; @@ -267,16 +267,16 @@ typedef enum eGP_SelectGrouped { static void gp_select_same_layer(bContext *C) { Scene *scene = CTX_data_scene(C); - + CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers) { bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, 0); bGPDstroke *gps; bool found = false; - + if (gpf == NULL) continue; - + /* Search for a selected stroke */ for (gps = gpf->strokes.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { @@ -286,18 +286,18 @@ static void gp_select_same_layer(bContext *C) } } } - + /* Select all if found */ if (found) { for (gps = gpf->strokes.first; gps; gps = gps->next) { if (ED_gpencil_stroke_can_use(C, gps)) { bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag |= GP_SPOINT_SELECT; } - + gps->flag |= GP_STROKE_SELECT; } } @@ -310,11 +310,11 @@ static void gp_select_same_layer(bContext *C) static void gp_select_same_color(bContext *C) { /* First, build set containing all the colors of selected strokes - * - We use the palette names, so that we can select all strokes with one + * - We use the palette names, so that we can select all strokes with one * (potentially missing) color, and remap them to something else */ GSet *selected_colors = BLI_gset_str_new("GP Selected Colors"); - + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { if (gps->flag & GP_STROKE_SELECT) { @@ -325,7 +325,7 @@ static void gp_select_same_color(bContext *C) } } CTX_DATA_END; - + /* Second, select any visible stroke that uses these colors */ CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { @@ -333,11 +333,11 @@ static void gp_select_same_color(bContext *C) /* select this stroke */ bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag |= GP_SPOINT_SELECT; } - + gps->flag |= GP_STROKE_SELECT; } } @@ -350,7 +350,7 @@ static void gp_select_same_color(bContext *C) static int gpencil_select_grouped_exec(bContext *C, wmOperator *op) { eGP_SelectGrouped mode = RNA_enum_get(op->ptr, "type"); - + switch (mode) { case GP_SEL_SAME_LAYER: gp_select_same_layer(C); @@ -358,12 +358,12 @@ static int gpencil_select_grouped_exec(bContext *C, wmOperator *op) case GP_SEL_SAME_COLOR: gp_select_same_color(C); break; - + default: BLI_assert(!"unhandled select grouped gpencil mode"); break; } - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -376,20 +376,20 @@ void GPENCIL_OT_select_grouped(wmOperatorType *ot) {GP_SEL_SAME_COLOR, "COLOR", 0, "Color", "Shared colors"}, {0, NULL, 0, NULL, NULL} }; - + /* identifiers */ ot->name = "Select Grouped"; ot->idname = "GPENCIL_OT_select_grouped"; ot->description = "Select all strokes with similar characteristics"; - + /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gpencil_select_grouped_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* props */ ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, GP_SEL_SAME_LAYER, "Type", ""); } @@ -401,33 +401,33 @@ static int gpencil_select_first_exec(bContext *C, wmOperator *op) { const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes"); const bool extend = RNA_boolean_get(op->ptr, "extend"); - + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { /* skip stroke if we're only manipulating selected strokes */ if (only_selected && !(gps->flag & GP_STROKE_SELECT)) { continue; } - + /* select first point */ BLI_assert(gps->totpoints >= 1); - + gps->points->flag |= GP_SPOINT_SELECT; gps->flag |= GP_STROKE_SELECT; - + /* deselect rest? */ if ((extend == false) && (gps->totpoints > 1)) { /* start from index 1, to skip the first point that we'd just selected... */ bGPDspoint *pt = &gps->points[1]; int i = 1; - + for (; i < gps->totpoints; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } } } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -439,18 +439,18 @@ void GPENCIL_OT_select_first(wmOperatorType *ot) ot->name = "Select First"; ot->idname = "GPENCIL_OT_select_first"; ot->description = "Select first point in Grease Pencil strokes"; - + /* callbacks */ ot->exec = gpencil_select_first_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ RNA_def_boolean(ot->srna, "only_selected_strokes", false, "Selected Strokes Only", "Only select the first point of strokes that already have points selected"); - + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting all other selected points"); } @@ -461,33 +461,33 @@ static int gpencil_select_last_exec(bContext *C, wmOperator *op) { const bool only_selected = RNA_boolean_get(op->ptr, "only_selected_strokes"); const bool extend = RNA_boolean_get(op->ptr, "extend"); - + CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { /* skip stroke if we're only manipulating selected strokes */ if (only_selected && !(gps->flag & GP_STROKE_SELECT)) { continue; } - + /* select last point */ BLI_assert(gps->totpoints >= 1); - + gps->points[gps->totpoints - 1].flag |= GP_SPOINT_SELECT; gps->flag |= GP_STROKE_SELECT; - + /* deselect rest? */ if ((extend == false) && (gps->totpoints > 1)) { /* don't include the last point... */ bGPDspoint *pt = gps->points; int i = 1; - + for (; i < gps->totpoints - 1; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } } } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -499,18 +499,18 @@ void GPENCIL_OT_select_last(wmOperatorType *ot) ot->name = "Select Last"; ot->idname = "GPENCIL_OT_select_last"; ot->description = "Select last point in Grease Pencil strokes"; - + /* callbacks */ ot->exec = gpencil_select_last_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ RNA_def_boolean(ot->srna, "only_selected_strokes", false, "Selected Strokes Only", "Only select the last point of strokes that already have points selected"); - + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting all other selected points"); } @@ -525,8 +525,8 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op)) bGPDspoint *pt; int i; bool prev_sel; - - /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)... + + /* First Pass: Go in forward order, expanding selection if previous was selected (pre changes)... * - This pass covers the "after" edges of selection islands */ prev_sel = false; @@ -543,8 +543,8 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op)) prev_sel = false; } } - - /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) + + /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) * - This pass covers the "before" edges of selection islands */ prev_sel = false; @@ -563,7 +563,7 @@ static int gpencil_select_more_exec(bContext *C, wmOperator *UNUSED(op)) } } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -575,11 +575,11 @@ void GPENCIL_OT_select_more(wmOperatorType *ot) ot->name = "Select More"; ot->idname = "GPENCIL_OT_select_more"; ot->description = "Grow sets of selected Grease Pencil points"; - + /* callbacks */ ot->exec = gpencil_select_more_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -595,8 +595,8 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op)) bGPDspoint *pt; int i; bool prev_sel; - - /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)... + + /* First Pass: Go in forward order, shrinking selection if previous was not selected (pre changes)... * - This pass covers the "after" edges of selection islands */ prev_sel = false; @@ -613,8 +613,8 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op)) prev_sel = false; } } - - /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) + + /* Second Pass: Go in reverse order, doing the same as before (except in opposite order) * - This pass covers the "before" edges of selection islands */ prev_sel = false; @@ -634,7 +634,7 @@ static int gpencil_select_less_exec(bContext *C, wmOperator *UNUSED(op)) } } CTX_DATA_END; - + /* updates */ WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); return OPERATOR_FINISHED; @@ -646,11 +646,11 @@ void GPENCIL_OT_select_less(wmOperatorType *ot) ot->name = "Select Less"; ot->idname = "GPENCIL_OT_select_less"; ot->description = "Shrink sets of selected Grease Pencil points"; - + /* callbacks */ ot->exec = gpencil_select_less_exec; ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } @@ -671,7 +671,7 @@ static bool gp_stroke_do_circle_sel( int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int i; bool changed = false; - + if (gps->totpoints == 1) { if (!parented) { gp_point_to_xy(gsc, gps, gps->points, &x0, &y0); @@ -681,7 +681,7 @@ static bool gp_stroke_do_circle_sel( gp_point_to_parent_space(gps->points, diff_mat, &pt_temp); gp_point_to_xy(gsc, gps, &pt_temp, &x0, &y0); } - + /* do boundbox check first */ if ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) { /* only check if point is inside */ @@ -695,13 +695,13 @@ static bool gp_stroke_do_circle_sel( gps->points->flag &= ~GP_SPOINT_SELECT; gps->flag &= ~GP_STROKE_SELECT; } - + return true; } } } else { - /* Loop over the points in the stroke, checking for intersections + /* Loop over the points in the stroke, checking for intersections * - an intersection means that we touched the stroke */ for (i = 0; (i + 1) < gps->totpoints; i++) { @@ -720,43 +720,43 @@ static bool gp_stroke_do_circle_sel( gp_point_to_parent_space(pt2, diff_mat, &npt); gp_point_to_xy(gsc, gps, &npt, &x1, &y1); } - + /* check that point segment of the boundbox of the selection stroke */ if (((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(rect, x0, y0)) || ((!ELEM(V2D_IS_CLIPPED, x1, y1)) && BLI_rcti_isect_pt(rect, x1, y1))) { int mval[2] = {mx, my}; int mvalo[2] = {mx, my}; /* dummy - this isn't used... */ - + /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant */ if (gp_stroke_inside_circle(mval, mvalo, radius, x0, y0, x1, y1)) { - /* change selection of stroke, and then of both points + /* change selection of stroke, and then of both points * (as the last point otherwise wouldn't get selected - * as we only do n-1 loops through) + * as we only do n-1 loops through) */ if (select) { pt1->flag |= GP_SPOINT_SELECT; pt2->flag |= GP_SPOINT_SELECT; - + changed = true; } else { pt1->flag &= ~GP_SPOINT_SELECT; pt2->flag &= ~GP_SPOINT_SELECT; - + changed = true; } } } } - + /* Ensure that stroke selection is in sync with its points */ BKE_gpencil_stroke_sync_selection(gps); } - + return changed; } @@ -764,36 +764,36 @@ static bool gp_stroke_do_circle_sel( static int gpencil_circle_select_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); - + const int mx = RNA_int_get(op->ptr, "x"); const int my = RNA_int_get(op->ptr, "y"); const int radius = RNA_int_get(op->ptr, "radius"); - + bool select = !RNA_boolean_get(op->ptr, "deselect"); - + GP_SpaceConversion gsc = {NULL}; rcti rect = {0}; /* for bounding rect around circle (for quicky intersection testing) */ - + bool changed = false; - - + + /* sanity checks */ if (sa == NULL) { BKE_report(op->reports, RPT_ERROR, "No active area"); return OPERATOR_CANCELLED; } - + /* init space conversion stuff */ gp_point_conversion_init(C, &gsc); - - + + /* rect is rectangle of selection circle */ rect.xmin = mx - radius; rect.ymin = my - radius; rect.xmax = mx + radius; rect.ymax = my + radius; - - + + /* find visible strokes, and select if hit */ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) { @@ -807,7 +807,7 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op) if (changed) { WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); } - + return OPERATOR_FINISHED; } @@ -817,17 +817,17 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot) ot->name = "Circle Select"; ot->description = "Select Grease Pencil strokes using brush selection"; ot->idname = "GPENCIL_OT_select_circle"; - + /* callbacks */ ot->invoke = WM_gesture_circle_invoke; ot->modal = WM_gesture_circle_modal; ot->exec = gpencil_circle_select_exec; ot->poll = gpencil_select_poll; ot->cancel = WM_gesture_circle_cancel; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ WM_operator_properties_gesture_circle_select(ot); } @@ -838,45 +838,45 @@ void GPENCIL_OT_select_circle(wmOperatorType *ot) static int gpencil_border_select_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); - + const bool select = !RNA_boolean_get(op->ptr, "deselect"); const bool extend = RNA_boolean_get(op->ptr, "extend"); - + GP_SpaceConversion gsc = {NULL}; rcti rect = {0}; - + bool changed = false; - - + + /* sanity checks */ if (sa == NULL) { BKE_report(op->reports, RPT_ERROR, "No active area"); return OPERATOR_CANCELLED; } - + /* init space conversion stuff */ gp_point_conversion_init(C, &gsc); - - + + /* deselect all strokes first? */ if (select && !extend) { CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } - + gps->flag &= ~GP_STROKE_SELECT; } CTX_DATA_END; } - + /* get settings from operator */ WM_operator_properties_border_to_rcti(op, &rect); - + /* select/deselect points */ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) { @@ -919,7 +919,7 @@ static int gpencil_border_select_exec(bContext *C, wmOperator *op) if (changed) { WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); } - + return OPERATOR_FINISHED; } @@ -929,18 +929,18 @@ void GPENCIL_OT_select_border(wmOperatorType *ot) ot->name = "Border Select"; ot->description = "Select Grease Pencil strokes within a rectangular region"; ot->idname = "GPENCIL_OT_select_border"; - + /* callbacks */ ot->invoke = WM_gesture_border_invoke; ot->exec = gpencil_border_select_exec; ot->modal = WM_gesture_border_modal; ot->cancel = WM_gesture_border_cancel; - + ot->poll = gpencil_select_poll; - + /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* rna */ WM_operator_properties_gesture_border_select(ot); } @@ -952,41 +952,41 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) { GP_SpaceConversion gsc = {NULL}; rcti rect = {0}; - + const bool extend = RNA_boolean_get(op->ptr, "extend"); const bool select = !RNA_boolean_get(op->ptr, "deselect"); - + int mcords_tot; const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); - + bool changed = false; - + /* sanity check */ if (mcords == NULL) return OPERATOR_PASS_THROUGH; - + /* compute boundbox of lasso (for faster testing later) */ BLI_lasso_boundbox(&rect, mcords, mcords_tot); - + /* init space conversion stuff */ gp_point_conversion_init(C, &gsc); - + /* deselect all strokes first? */ if (select && !extend) { CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) { bGPDspoint *pt; int i; - + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } - + gps->flag &= ~GP_STROKE_SELECT; } CTX_DATA_END; } - + /* select/deselect points */ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) { @@ -1027,12 +1027,12 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) /* cleanup */ MEM_freeN((void *)mcords); - + /* updates */ if (changed) { WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); } - + return OPERATOR_FINISHED; } @@ -1041,16 +1041,16 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot) ot->name = "Lasso Select Strokes"; ot->description = "Select Grease Pencil strokes using lasso selection"; ot->idname = "GPENCIL_OT_select_lasso"; - + ot->invoke = WM_gesture_lasso_invoke; ot->modal = WM_gesture_lasso_modal; ot->exec = gpencil_lasso_select_exec; ot->poll = gpencil_select_poll; ot->cancel = WM_gesture_lasso_cancel; - + /* flags */ ot->flag = OPTYPE_UNDO; - + /* properties */ WM_operator_properties_gesture_lasso_select(ot); } @@ -1061,36 +1061,36 @@ void GPENCIL_OT_select_lasso(wmOperatorType *ot) static int gpencil_select_exec(bContext *C, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); - + /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */ const float radius = 0.75f * U.widget_unit; const int radius_squared = (int)(radius * radius); - + bool extend = RNA_boolean_get(op->ptr, "extend"); bool deselect = RNA_boolean_get(op->ptr, "deselect"); bool toggle = RNA_boolean_get(op->ptr, "toggle"); bool whole = RNA_boolean_get(op->ptr, "entire_strokes"); - + int mval[2] = {0}; - + GP_SpaceConversion gsc = {NULL}; - + bGPDstroke *hit_stroke = NULL; bGPDspoint *hit_point = NULL; int hit_distance = radius_squared; - + /* sanity checks */ if (sa == NULL) { BKE_report(op->reports, RPT_ERROR, "No active area"); return OPERATOR_CANCELLED; } - + /* init space conversion stuff */ gp_point_conversion_init(C, &gsc); - + /* get mouse location */ RNA_int_get_array(op->ptr, "location", mval); - + /* First Pass: Find stroke point which gets hit */ /* XXX: maybe we should go from the top of the stack down instead... */ GP_EDITABLE_STROKES_BEGIN(C, gpl, gps) @@ -1133,38 +1133,38 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) if (ELEM(NULL, hit_stroke, hit_point)) { return OPERATOR_CANCELLED; } - + /* adjust selection behaviour - for toggle option */ if (toggle) { deselect = (hit_point->flag & GP_SPOINT_SELECT) != 0; } - + /* If not extending selection, deselect everything else */ if (extend == false) { CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes) - { + { /* deselect stroke and its points if selected */ if (gps->flag & GP_STROKE_SELECT) { bGPDspoint *pt; int i; - + /* deselect points */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { pt->flag &= ~GP_SPOINT_SELECT; } - + /* deselect stroke itself too */ gps->flag &= ~GP_STROKE_SELECT; } } CTX_DATA_END; } - + /* Perform selection operations... */ if (whole) { bGPDspoint *pt; int i; - + /* entire stroke's points */ for (i = 0, pt = hit_stroke->points; i < hit_stroke->totpoints; i++, pt++) { if (deselect == false) @@ -1172,7 +1172,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) else pt->flag &= ~GP_SPOINT_SELECT; } - + /* stroke too... */ if (deselect == false) hit_stroke->flag |= GP_STROKE_SELECT; @@ -1189,17 +1189,17 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) else { /* deselect point */ hit_point->flag &= ~GP_SPOINT_SELECT; - + /* ensure that stroke is selected correctly */ BKE_gpencil_stroke_sync_selection(hit_stroke); } } - + /* updates */ if (hit_point != NULL) { WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); } - + return OPERATOR_FINISHED; } @@ -1212,26 +1212,26 @@ static int gpencil_select_invoke(bContext *C, wmOperator *op, const wmEvent *eve void GPENCIL_OT_select(wmOperatorType *ot) { PropertyRNA *prop; - + /* identifiers */ ot->name = "Select"; ot->description = "Select Grease Pencil strokes and/or stroke points"; ot->idname = "GPENCIL_OT_select"; - + /* callbacks */ ot->invoke = gpencil_select_invoke; ot->exec = gpencil_select_exec; ot->poll = gpencil_select_poll; - + /* flag */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - + /* properties */ WM_operator_properties_mouse_select(ot); - + prop = RNA_def_boolean(ot->srna, "entire_strokes", false, "Entire Strokes", "Select entire strokes instead of just the nearest stroke vertex"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); - + prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN); } diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index 202d7630ae0..5e2be7c41f0 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -55,7 +55,7 @@ typedef struct bGPundonode { struct bGPundonode *next, *prev; - + char name[BKE_UNDO_STR_MAX]; struct bGPdata *gpd; } bGPundonode; @@ -71,9 +71,9 @@ int ED_gpencil_session_active(void) int ED_undo_gpencil_step(bContext *C, int step, const char *name) { bGPdata **gpd_ptr = NULL, *new_gpd = NULL; - + gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - + if (step == 1) { /* undo */ //printf("\t\tGP - undo step\n"); if (cur_node->prev) { @@ -92,18 +92,18 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name) } } } - + if (new_gpd) { if (gpd_ptr) { if (*gpd_ptr) { bGPdata *gpd = *gpd_ptr; bGPDlayer *gpl, *gpld; - + BKE_gpencil_free_layers(&gpd->layers); - + /* copy layers */ BLI_listbase_clear(&gpd->layers); - + for (gpl = new_gpd->layers.first; gpl; gpl = gpl->next) { /* make a copy of source layer and its data */ gpld = BKE_gpencil_layer_duplicate(gpl); @@ -112,9 +112,9 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name) } } } - + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); - + return OPERATOR_FINISHED; } @@ -129,7 +129,7 @@ static void gpencil_undo_free_node(bGPundonode *undo_node) * or else the real copy will segfault when accessed */ undo_node->gpd->adt = NULL; - + BKE_gpencil_free(undo_node->gpd, false); MEM_freeN(undo_node->gpd); } @@ -137,65 +137,65 @@ static void gpencil_undo_free_node(bGPundonode *undo_node) void gpencil_undo_push(bGPdata *gpd) { bGPundonode *undo_node; - + //printf("\t\tGP - undo push\n"); - + if (cur_node) { /* remove all un-done nodes from stack */ undo_node = cur_node->next; - + while (undo_node) { bGPundonode *next_node = undo_node->next; - + gpencil_undo_free_node(undo_node); BLI_freelinkN(&undo_nodes, undo_node); - + undo_node = next_node; } } - + /* limit number of undo steps to the maximum undo steps - * - to prevent running out of memory during **really** + * - to prevent running out of memory during **really** * long drawing sessions (triggering swapping) */ /* TODO: Undo-memory constraint is not respected yet, but can be added if we have any need for it */ if (U.undosteps && !BLI_listbase_is_empty(&undo_nodes)) { /* remove anything older than n-steps before cur_node */ int steps = 0; - + undo_node = (cur_node) ? cur_node : undo_nodes.last; while (undo_node) { bGPundonode *prev_node = undo_node->prev; - + if (steps >= U.undosteps) { gpencil_undo_free_node(undo_node); BLI_freelinkN(&undo_nodes, undo_node); } - + steps++; undo_node = prev_node; } } - + /* create new undo node */ undo_node = MEM_callocN(sizeof(bGPundonode), "gpencil undo node"); undo_node->gpd = BKE_gpencil_data_duplicate(G.main, gpd, true); - + cur_node = undo_node; - + BLI_addtail(&undo_nodes, undo_node); } void gpencil_undo_finish(void) { bGPundonode *undo_node = undo_nodes.first; - + while (undo_node) { gpencil_undo_free_node(undo_node); undo_node = undo_node->next; } - + BLI_freelistN(&undo_nodes); - + cur_node = NULL; } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 672c87ed6fd..707afa72c6a 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -80,16 +80,16 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr */ if (sa) { SpaceLink *sl = sa->spacedata.first; - + switch (sa->spacetype) { case SPACE_VIEW3D: /* 3D-View */ { BLI_assert(scene && ELEM(scene->toolsettings->gpencil_src, GP_TOOL_SOURCE_SCENE, GP_TOOL_SOURCE_OBJECT)); - + if (scene->toolsettings->gpencil_src == GP_TOOL_SOURCE_OBJECT) { /* legacy behaviour for usage with old addons requiring object-linked to objects */ - + /* just in case no active/selected object... */ if (ob && (ob->flag & SELECT)) { /* for now, as long as there's an object, default to using that in 3D-View */ @@ -107,21 +107,21 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr case SPACE_NODE: /* Nodes Editor */ { SpaceNode *snode = (SpaceNode *)sl; - + /* return the GP data for the active node block/node */ if (snode && snode->nodetree) { /* for now, as long as there's an active node tree, default to using that in the Nodes Editor */ if (ptr) RNA_id_pointer_create(&snode->nodetree->id, ptr); return &snode->nodetree->gpd; } - + /* even when there is no node-tree, don't allow this to flow to scene */ return NULL; } case SPACE_SEQ: /* Sequencer */ { SpaceSeq *sseq = (SpaceSeq *)sl; - + /* for now, Grease Pencil data is associated with the space (actually preview region only) */ /* XXX our convention for everything else is to link to data though... */ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceSequenceEditor, sseq, ptr); @@ -130,7 +130,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr case SPACE_IMAGE: /* Image/UV Editor */ { SpaceImage *sima = (SpaceImage *)sl; - + /* for now, Grease Pencil data is associated with the space... */ /* XXX our convention for everything else is to link to data though... */ if (ptr) RNA_pointer_create(screen_id, &RNA_SpaceImageEditor, sima, ptr); @@ -140,23 +140,23 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr { SpaceClip *sc = (SpaceClip *)sl; MovieClip *clip = ED_space_clip_get_clip(sc); - + if (clip) { if (sc->gpencil_src == SC_GPENCIL_SRC_TRACK) { MovieTrackingTrack *track = BKE_tracking_track_get_active(&clip->tracking); - + if (!track) return NULL; - + if (ptr) RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, ptr); - + return &track->gpd; } else { if (ptr) RNA_id_pointer_create(&clip->id, ptr); - + return &clip->gpd; } } @@ -166,7 +166,7 @@ bGPdata **ED_gpencil_data_get_pointers_direct(ID *screen_id, Scene *scene, ScrAr return NULL; } } - + /* just fall back on the scene's GP data */ if (ptr) RNA_id_pointer_create((ID *)scene, ptr); return (scene) ? &scene->gpd : NULL; @@ -179,7 +179,7 @@ bGPdata **ED_gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) Scene *scene = CTX_data_scene(C); ScrArea *sa = CTX_wm_area(C); Object *ob = CTX_data_active_object(C); - + return ED_gpencil_data_get_pointers_direct(screen_id, scene, sa, ob, ptr); } @@ -209,7 +209,7 @@ bGPdata *ED_gpencil_data_get_active_v3d(Scene *scene, View3D *v3d) /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, * to be consistent with ED_gpencil_data_get_active's behavior. */ - + if (base && TESTBASE(v3d, base)) { gpd = base->object->gpd; } @@ -237,7 +237,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra) } } } - + if (ob && ob->gpd) { bGPDlayer *gpl = BKE_gpencil_layer_getactive(ob->gpd); if (gpl) { @@ -251,7 +251,7 @@ bool ED_gpencil_has_keyframe_v3d(Scene *scene, Object *ob, int cfra) } } } - + return false; } @@ -270,7 +270,7 @@ int gp_active_layer_poll(bContext *C) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd); - + return (gpl != NULL); } @@ -315,25 +315,25 @@ const EnumPropertyItem *ED_gpencil_layers_enum_itemf( EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; int i = 0; - + if (ELEM(NULL, C, gpd)) { return DummyRNA_DEFAULT_items; } - + /* Existing layers */ for (gpl = gpd->layers.first; gpl; gpl = gpl->next, i++) { item_tmp.identifier = gpl->info; item_tmp.name = gpl->info; item_tmp.value = i; - + if (gpl->flag & GP_LAYER_ACTIVE) item_tmp.icon = ICON_GREASEPENCIL; - else + else item_tmp.icon = ICON_NONE; - + RNA_enum_item_add(&item, &totitem, &item_tmp); } - + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -349,11 +349,11 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf( EnumPropertyItem *item = NULL, item_tmp = {0}; int totitem = 0; int i = 0; - + if (ELEM(NULL, C, gpd)) { return DummyRNA_DEFAULT_items; } - + /* Create new layer */ /* TODO: have some way of specifying that we don't want this? */ { @@ -363,25 +363,25 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf( item_tmp.value = -1; item_tmp.icon = ICON_ZOOMIN; RNA_enum_item_add(&item, &totitem, &item_tmp); - + /* separator */ RNA_enum_item_add_separator(&item, &totitem); } - + /* Existing layers */ for (gpl = gpd->layers.first, i = 0; gpl; gpl = gpl->next, i++) { item_tmp.identifier = gpl->info; item_tmp.name = gpl->info; item_tmp.value = i; - + if (gpl->flag & GP_LAYER_ACTIVE) item_tmp.icon = ICON_GREASEPENCIL; - else + else item_tmp.icon = ICON_NONE; - + RNA_enum_item_add(&item, &totitem, &item_tmp); } - + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -410,11 +410,11 @@ bool gp_stroke_inside_circle(const int mval[2], const int UNUSED(mvalo[2]), const float mval_fl[2] = {mval[0], mval[1]}; const float screen_co_a[2] = {x0, y0}; const float screen_co_b[2] = {x1, y1}; - + if (edge_inside_circle(mval_fl, rad, screen_co_a, screen_co_b)) { return true; } - + /* not inside */ return false; } @@ -467,7 +467,7 @@ bool ED_gpencil_stroke_color_use(const bGPDlayer *gpl, const bGPDstroke *gps) if (((gpl->flag & GP_LAYER_UNLOCK_COLOR) == 0) && (palcolor->flag & PC_COLOR_LOCKED)) return false; } - + return true; } @@ -522,29 +522,29 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); - + /* zero out the storage (just in case) */ memset(r_gsc, 0, sizeof(GP_SpaceConversion)); unit_m4(r_gsc->mat); - + /* store settings */ r_gsc->sa = sa; r_gsc->ar = ar; r_gsc->v2d = &ar->v2d; - + /* init region-specific stuff */ if (sa->spacetype == SPACE_VIEW3D) { wmWindow *win = CTX_wm_window(C); Scene *scene = CTX_data_scene(C); View3D *v3d = (View3D *)CTX_wm_space_data(C); RegionView3D *rv3d = ar->regiondata; - + /* init 3d depth buffers */ view3d_operator_needs_opengl(C); - + view3d_region_operator_needs_opengl(win, ar); ED_view3d_autodist_init(scene, ar, v3d, 0); - + /* for camera view set the subrect */ if (rv3d->persp == RV3D_CAMOB) { ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &r_gsc->subrect_data, true); /* no shift */ @@ -560,7 +560,7 @@ void gp_point_conversion_init(bContext *C, GP_SpaceConversion *r_gsc) * \param diff_mat Matrix with the difference between original parent matrix * \param[out] r_pt Pointer to new point after apply matrix */ -void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt) +void gp_point_to_parent_space(bGPDspoint *pt, float diff_mat[4][4], bGPDspoint *r_pt) { float fpt[3]; @@ -623,12 +623,12 @@ void gp_point_to_xy(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, View2D *v2d = gsc->v2d; rctf *subrect = gsc->subrect; int xyval[2]; - + /* sanity checks */ BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); - - + + if (gps->flag & GP_STROKE_3DSPACE) { if (ED_view3d_project_int_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { *r_x = xyval[0]; @@ -676,12 +676,12 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, View2D *v2d = gsc->v2d; rctf *subrect = gsc->subrect; float xyval[2]; - + /* sanity checks */ BLI_assert(!(gps->flag & GP_STROKE_3DSPACE) || (gsc->sa->spacetype == SPACE_VIEW3D)); BLI_assert(!(gps->flag & GP_STROKE_2DSPACE) || (gsc->sa->spacetype != SPACE_VIEW3D)); - - + + if (gps->flag & GP_STROKE_3DSPACE) { if (ED_view3d_project_float_global(ar, &pt->x, xyval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { *r_x = xyval[0]; @@ -695,10 +695,10 @@ void gp_point_to_xy_fl(GP_SpaceConversion *gsc, bGPDstroke *gps, bGPDspoint *pt, else if (gps->flag & GP_STROKE_2DSPACE) { float vec[3] = {pt->x, pt->y, 0.0f}; int t_x, t_y; - + mul_m4_v3(gsc->mat, vec); UI_view2d_view_to_region_clip(v2d, vec[0], vec[1], &t_x, &t_y); - + if ((t_x == t_y) && (t_x == V2D_IS_CLIPPED)) { /* XXX: Or should we just always use the values as-is? */ *r_x = 0.0f; @@ -745,22 +745,22 @@ bool gp_point_xy_to_3d(GP_SpaceConversion *gsc, Scene *scene, const float screen float *rvec = ED_view3d_cursor3d_get(scene, v3d); float ref[3] = {rvec[0], rvec[1], rvec[2]}; float zfac = ED_view3d_calc_zfac(rv3d, rvec, NULL); - + float mval_f[2], mval_prj[2]; float dvec[3]; - + copy_v2_v2(mval_f, screen_co); - + if (ED_view3d_project_float_global(gsc->ar, ref, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { sub_v2_v2v2(mval_f, mval_prj, mval_f); ED_view3d_win_to_delta(gsc->ar, mval_f, dvec, zfac); sub_v3_v3v3(r_out, rvec, dvec); - + return true; } else { zero_v3(r_out); - + return false; } } @@ -777,19 +777,19 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure) bGPDspoint *pt = &gps->points[i]; float pressure = 0.0f; float sco[3] = {0.0f}; - + /* Do nothing if not enough points to smooth out */ if (gps->totpoints <= 2) { return false; } - + /* Only affect endpoints by a fraction of the normal strength, * to prevent the stroke from shrinking too much */ if ((i == 0) || (i == gps->totpoints - 1)) { inf *= 0.1f; } - + /* Compute smoothed coordinate by taking the ones nearby */ /* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */ { @@ -797,14 +797,14 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure) const int steps = 2; const float average_fac = 1.0f / (float)(steps * 2 + 1); int step; - + /* add the point itself */ madd_v3_v3fl(sco, &pt->x, average_fac); - + if (affect_pressure) { pressure += pt->pressure * average_fac; } - + /* n-steps before/after current point */ // XXX: review how the endpoints are treated by this algorithm // XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight @@ -812,17 +812,17 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure) bGPDspoint *pt1, *pt2; int before = i - step; int after = i + step; - + CLAMP_MIN(before, 0); CLAMP_MAX(after, gps->totpoints - 1); - + pt1 = &gps->points[before]; pt2 = &gps->points[after]; - + /* add both these points to the average-sum (s += p[i]/n) */ madd_v3_v3fl(sco, &pt1->x, average_fac); madd_v3_v3fl(sco, &pt2->x, average_fac); - + #if 0 /* XXX: Disabled because get weird result */ /* do pressure too? */ @@ -833,17 +833,17 @@ bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure) #endif } } - + /* Based on influence factor, blend between original and optimal smoothed coordinate */ interp_v3_v3v3(&pt->x, &pt->x, sco, inf); - + #if 0 /* XXX: Disabled because get weird result */ if (affect_pressure) { pt->pressure = pressure; } #endif - + return true; } @@ -936,22 +936,22 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints) gps->points[new_totpoints - y] = gps->points[i]; y += 2; } - + /* Create interpolated points */ for (int i = 0; i < new_totpoints - 1; i += 2) { bGPDspoint *prev = &gps->points[i]; bGPDspoint *pt = &gps->points[i + 1]; bGPDspoint *next = &gps->points[i + 2]; - + /* Interpolate all values */ interp_v3_v3v3(&pt->x, &prev->x, &next->x, 0.5f); - + pt->pressure = interpf(prev->pressure, next->pressure, 0.5f); pt->strength = interpf(prev->strength, next->strength, 0.5f); CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = interpf(prev->time, next->time, 0.5f); } - + /* Update to new total number of points */ gps->totpoints = new_totpoints; } @@ -984,12 +984,12 @@ void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush) float normal[3]; cross_v3_v3v3(normal, v1, v2); normalize_v3(normal); - + /* get orthogonal vector to plane to rotate random effect */ float ortho[3]; cross_v3_v3v3(ortho, v1, normal); normalize_v3(ortho); - + /* Read all points and apply shift vector (first and last point not modified) */ for (int i = 1; i < gps->totpoints - 1; ++i) { bGPDspoint *pt = &gps->points[i]; |