Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-06-04 10:31:30 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-06-04 10:31:30 +0300
commit44505b38df557a5711703613685a1dec9fc2c3d9 (patch)
tree3f05bebcc7bfadf56569f2dcca7f95fc56b1b0d0 /source/blender/editors/gpencil
parent6654e109df952be3a3128fae2508a02c196ae593 (diff)
Cleanup: strip trailing space in editors
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c358
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c152
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c460
-rw-r--r--source/blender/editors/gpencil/gpencil_convert.c324
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c164
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c576
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c280
-rw-r--r--source/blender/editors/gpencil/gpencil_ops.c164
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c516
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c324
-rw-r--r--source/blender/editors/gpencil/gpencil_undo.c52
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c148
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, &gtd);
-
+
/* 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, &region_rect);
in_bounds = BLI_rcti_isect_pt_v(&region_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];