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:
authorCharlie Jolly <mistajolly@gmail.com>2019-09-06 16:07:26 +0300
committerCharlie Jolly <mistajolly@gmail.com>2019-09-06 16:07:26 +0300
commita94bf0e1349b4ee39e308a565fe26a4bd7cb7543 (patch)
treea96bfdc616edba9546ce6dc613228b4d4ea4ec07 /source/blender/editors/gpencil/gpencil_paint.c
parent4c20c53b8980535fd0d62a5285a1e27bbe6e829d (diff)
GPencil: Guides: Refactor and add new ISO option
+ Simplify code, move into own function and run once rather than on every point + Improved snapping when a stroke is between increments + Added ISO grid option for lines specified by Angle under guide settings + Radial snapping mode uses Angle as an offset Differential Revision: https://developer.blender.org/D5668
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_paint.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c304
1 files changed, 185 insertions, 119 deletions
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 3217c94eebd..a585d3b71fc 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -113,6 +113,28 @@ typedef enum eGPencil_PaintFlags {
GP_PAINTFLAG_REQ_VECTOR = (1 << 6),
} eGPencil_PaintFlags;
+/* Temporary Guide data */
+typedef struct tGPguide {
+ /** guide spacing */
+ float spacing;
+ /** half guide spacing */
+ float half_spacing;
+ /** origin */
+ float origin[2];
+ /** rotated point */
+ float rot_point[2];
+ /** rotated point */
+ float rot_angle;
+ /** initial stroke direction */
+ float stroke_angle;
+ /** initial origin direction */
+ float origin_angle;
+ /** initial origin distance */
+ float origin_distance;
+ /** initial line for guides */
+ float unit[2];
+} tGPguide;
+
/* Temporary 'Stroke' Operation data
* "p" = op->customdata
*/
@@ -224,12 +246,7 @@ typedef struct tGPsdata {
float totpixlen;
/* guide */
- /** guide spacing */
- float guide_spacing;
- /** half guide spacing */
- float half_spacing;
- /** origin */
- float origin[2];
+ tGPguide guide;
ReportList *reports;
} tGPsdata;
@@ -2642,19 +2659,26 @@ static void gp_rotate_v2_v2v2fl(float v[2],
static float gp_snap_to_grid_fl(float v, const float offset, const float spacing)
{
if (spacing > 0.0f) {
- return roundf(v / spacing) * spacing + fmodf(offset, spacing);
+ v -= spacing * 0.5f;
+ v -= offset;
+ v = roundf((v + spacing * 0.5f) / spacing) * spacing;
+ v += offset;
+ return v;
}
else {
return v;
}
}
-static void UNUSED_FUNCTION(gp_snap_to_grid_v2)(float v[2],
- const float offset[2],
- const float spacing)
+/* Helper to snap value to grid */
+static void gp_snap_to_rotated_grid_fl(float v[2],
+ const float origin[2],
+ const float spacing,
+ const float angle)
{
- v[0] = gp_snap_to_grid_fl(v[0], offset[0], spacing);
- v[1] = gp_snap_to_grid_fl(v[1], offset[1], spacing);
+ gp_rotate_v2_v2v2fl(v, v, origin, -angle);
+ v[1] = gp_snap_to_grid_fl(v[1], origin[1], spacing);
+ gp_rotate_v2_v2v2fl(v, v, origin, angle);
}
/* get reference point - screen coords to buffer coords */
@@ -2692,6 +2716,105 @@ static void gp_origin_get(tGPsdata *p, float origin[2])
gp_point_3d_to_xy(gsc, p->gpd->runtime.sbuffer_sflag, location, origin);
}
+/* speed guide initial values */
+static void gpencil_speed_guide_init(tGPsdata *p, GP_Sculpt_Guide *guide)
+{
+ /* calculate initial guide values */
+ RegionView3D *rv3d = p->ar->regiondata;
+ float scale = 1.0f;
+ if (rv3d->is_persp) {
+ float vec[3];
+ gp_get_3d_reference(p, vec);
+ mul_m4_v3(rv3d->persmat, vec);
+ scale = vec[2] * rv3d->pixsize;
+ }
+ else {
+ scale = rv3d->pixsize;
+ }
+ p->guide.spacing = guide->spacing / scale;
+ p->guide.half_spacing = p->guide.spacing * 0.5f;
+ gp_origin_get(p, p->guide.origin);
+
+ /* reference for angled snap */
+ copy_v2_v2(p->guide.unit, p->mvali);
+ p->guide.unit[0] += 1.0f;
+
+ float xy[2];
+ sub_v2_v2v2(xy, p->mvali, p->guide.origin);
+ p->guide.origin_angle = atan2f(xy[1], xy[0]) + (M_PI * 2.0f);
+
+ p->guide.origin_distance = len_v2v2(p->mvali, p->guide.origin);
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ p->guide.origin_distance = gp_snap_to_grid_fl(
+ p->guide.origin_distance, 0.0f, p->guide.spacing);
+ }
+
+ if (ELEM(guide->type, GP_GUIDE_RADIAL)) {
+ float angle;
+ float half_angle = guide->angle_snap * 0.5f;
+ angle = p->guide.origin_angle + guide->angle;
+ angle = fmodf(angle + half_angle, guide->angle_snap);
+ angle -= half_angle;
+ gp_rotate_v2_v2v2fl(p->guide.rot_point, p->mvali, p->guide.origin, -angle );
+ }
+ else {
+ gp_rotate_v2_v2v2fl(p->guide.rot_point, p->guide.unit, p->mvali, guide->angle);
+ }
+}
+
+/* apply speed guide */
+static void gpencil_speed_guide(tGPsdata *p, GP_Sculpt_Guide *guide)
+{
+ switch (guide->type) {
+ default:
+ case GP_GUIDE_CIRCULAR: {
+ dist_ensure_v2_v2fl(p->mval, p->guide.origin, p->guide.origin_distance);
+ break;
+ }
+ case GP_GUIDE_RADIAL: {
+ if (guide->use_snapping && (guide->angle_snap > 0.0f)) {
+ closest_to_line_v2(p->mval, p->mval, p->guide.rot_point, p->guide.origin);
+ }
+ else {
+ closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.origin);
+ }
+ break;
+ }
+ case GP_GUIDE_PARALLEL: {
+ closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.rot_point);
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ gp_snap_to_rotated_grid_fl(p->mval, p->guide.origin, p->guide.spacing, guide->angle);
+ }
+ break;
+ }
+ case GP_GUIDE_ISO: {
+ closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.rot_point);
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ gp_snap_to_rotated_grid_fl(p->mval, p->guide.origin, p->guide.spacing, p->guide.rot_angle);
+ }
+ break;
+ }
+ case GP_GUIDE_GRID: {
+ if (guide->use_snapping && (guide->spacing > 0.0f)) {
+ closest_to_line_v2(p->mval, p->mval, p->mvali, p->guide.rot_point);
+ if (p->straight == STROKE_HORIZONTAL) {
+ p->mval[1] = gp_snap_to_grid_fl(p->mval[1], p->guide.origin[1], p->guide.spacing);
+ }
+ else {
+ p->mval[0] = gp_snap_to_grid_fl(p->mval[0], p->guide.origin[0], p->guide.spacing);
+ }
+ }
+ else if (p->straight == STROKE_HORIZONTAL) {
+ p->mval[1] = p->mvali[1]; /* replace y */
+ }
+ else {
+ p->mval[0] = p->mvali[0]; /* replace x */
+ }
+ break;
+ }
+ }
+}
+
/* handle draw event */
static void gpencil_draw_apply_event(
bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
@@ -2726,6 +2849,10 @@ static void gpencil_draw_apply_event(
p->straight = STROKE_VERTICAL;
}
}
+ /* reset if a stroke angle is required */
+ if ((p->flags & GP_PAINTFLAG_REQ_VECTOR) && ((dx == 0) || (dy == 0))) {
+ p->straight = 0;
+ }
}
}
@@ -2773,6 +2900,14 @@ static void gpencil_draw_apply_event(
/* special exception for start of strokes (i.e. maybe for just a dot) */
if (p->flags & GP_PAINTFLAG_FIRSTRUN) {
+
+ /* special exception here for too high pressure values on first touch in
+ * windows for some tablets, then we just skip first touch...
+ */
+ if (tablet && (p->pressure >= 0.99f)) {
+ return;
+ }
+
p->flags &= ~GP_PAINTFLAG_FIRSTRUN;
/* set values */
@@ -2784,51 +2919,58 @@ static void gpencil_draw_apply_event(
/* save initial mouse */
copy_v2_v2(p->mvali, p->mval);
- /* calculate once and store snapping distance and origin */
- RegionView3D *rv3d = p->ar->regiondata;
- float scale = 1.0f;
- if (rv3d->is_persp) {
- float vec[3];
- gp_get_3d_reference(p, vec);
- mul_m4_v3(rv3d->persmat, vec);
- scale = vec[2] * rv3d->pixsize;
- }
- else {
- scale = rv3d->pixsize;
- }
- p->guide_spacing = guide->spacing / scale;
- p->half_spacing = p->guide_spacing * 0.5f;
- gp_origin_get(p, p->origin);
-
- /* special exception here for too high pressure values on first touch in
- * windows for some tablets, then we just skip first touch...
- */
- if (tablet && (p->pressure >= 0.99f)) {
- return;
+ if (is_speed_guide && !ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP) &&
+ ((guide->use_snapping && (guide->type == GP_GUIDE_GRID)) ||
+ (guide->type == GP_GUIDE_ISO)))
+ {
+ p->flags |= GP_PAINTFLAG_REQ_VECTOR;
}
- /* special exception for grid snapping
- * it requires direction which needs at least two points
- */
- if (!ELEM(p->paintmode, GP_PAINTMODE_ERASER, GP_PAINTMODE_SET_CP) && is_speed_guide &&
- guide->use_snapping && (guide->type == GP_GUIDE_GRID)) {
- p->flags |= GP_PAINTFLAG_REQ_VECTOR;
+ /* calculate initial guide values */
+ if (is_speed_guide) {
+ gpencil_speed_guide_init(p, guide);
}
}
/* wait for vector then add initial point */
- if (p->flags & GP_PAINTFLAG_REQ_VECTOR) {
+ if (is_speed_guide && p->flags & GP_PAINTFLAG_REQ_VECTOR) {
if (p->straight == 0) {
return;
}
p->flags &= ~GP_PAINTFLAG_REQ_VECTOR;
+ /* get initial point */
+ float pt[2];
+ sub_v2_v2v2(pt, p->mval, p->mvali);
+
+ /* get stroke angle for grids */
+ if (ELEM(guide->type, GP_GUIDE_ISO)) {
+ p->guide.stroke_angle = atan2f(pt[1], pt[0]);
+ /* determine iso angle, less weight is given for vertical strokes */
+ if (((p->guide.stroke_angle >= 0.0f) && (p->guide.stroke_angle < DEG2RAD(75))) ||
+ (p->guide.stroke_angle < DEG2RAD(-105))) {
+ p->guide.rot_angle = guide->angle;
+ }
+ else if (((p->guide.stroke_angle < 0.0f) && (p->guide.stroke_angle > DEG2RAD(-75))) ||
+ (p->guide.stroke_angle > DEG2RAD(105))) {
+ p->guide.rot_angle = -guide->angle;
+ }
+ else {
+ p->guide.rot_angle = DEG2RAD(90);
+ }
+ gp_rotate_v2_v2v2fl(p->guide.rot_point, p->guide.unit, p->mvali, p->guide.rot_angle);
+ }
+ else if (ELEM(guide->type, GP_GUIDE_GRID)) {
+ gp_rotate_v2_v2v2fl(p->guide.rot_point,
+ p->guide.unit,
+ p->mvali,
+ (p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f);
+ }
+
/* create fake events */
float tmp[2];
- float pt[2];
copy_v2_v2(tmp, p->mval);
- sub_v2_v2v2(pt, p->mval, p->mvali);
gpencil_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
if (len_v2v2(p->mval, p->mvalo)) {
sub_v2_v2v2(pt, p->mval, p->mvalo);
@@ -2841,83 +2983,7 @@ static void gpencil_draw_apply_event(
if ((p->paintmode != GP_PAINTMODE_ERASER) && ((p->straight) || (is_speed_guide))) {
/* guided stroke */
if (is_speed_guide) {
- switch (guide->type) {
- default:
- case GP_GUIDE_CIRCULAR: {
- float distance;
- distance = len_v2v2(p->mvali, p->origin);
-
- if (guide->use_snapping && (guide->spacing > 0.0f)) {
- distance = gp_snap_to_grid_fl(distance, 0.0f, p->guide_spacing);
- }
-
- dist_ensure_v2_v2fl(p->mval, p->origin, distance);
- break;
- }
- case GP_GUIDE_RADIAL: {
- if (guide->use_snapping && (guide->angle_snap > 0.0f)) {
- float point[2];
- float xy[2];
- float angle;
- float half_angle = guide->angle_snap * 0.5f;
- sub_v2_v2v2(xy, p->mvali, p->origin);
- angle = atan2f(xy[1], xy[0]);
- angle += (M_PI * 2.0f);
- angle = fmodf(angle + half_angle, guide->angle_snap);
- angle -= half_angle;
- gp_rotate_v2_v2v2fl(point, p->mvali, p->origin, -angle);
- closest_to_line_v2(p->mval, p->mval, point, p->origin);
- }
- else {
- closest_to_line_v2(p->mval, p->mval, p->mvali, p->origin);
- }
- break;
- }
- case GP_GUIDE_PARALLEL: {
- float point[2];
- float unit[2];
- copy_v2_v2(unit, p->mvali);
- unit[0] += 1.0f; /* start from horizontal */
- gp_rotate_v2_v2v2fl(point, unit, p->mvali, guide->angle);
- closest_to_line_v2(p->mval, p->mval, p->mvali, point);
-
- if (guide->use_snapping && (guide->spacing > 0.0f)) {
- gp_rotate_v2_v2v2fl(p->mval, p->mval, p->origin, -guide->angle);
- p->mval[1] = gp_snap_to_grid_fl(
- p->mval[1] - p->half_spacing, p->origin[1], p->guide_spacing);
- gp_rotate_v2_v2v2fl(p->mval, p->mval, p->origin, guide->angle);
- }
- break;
- }
- case GP_GUIDE_GRID: {
- if (guide->use_snapping && (guide->spacing > 0.0f)) {
- float point[2];
- float unit[2];
- float angle;
- copy_v2_v2(unit, p->mvali);
- unit[0] += 1.0f; /* start from horizontal */
- angle = (p->straight == STROKE_VERTICAL) ? M_PI_2 : 0.0f;
- gp_rotate_v2_v2v2fl(point, unit, p->mvali, angle);
- closest_to_line_v2(p->mval, p->mval, p->mvali, point);
-
- if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = gp_snap_to_grid_fl(
- p->mval[1] - p->half_spacing, p->origin[1], p->guide_spacing);
- }
- else {
- p->mval[0] = gp_snap_to_grid_fl(
- p->mval[0] - p->half_spacing, p->origin[0], p->guide_spacing);
- }
- }
- else if (p->straight == STROKE_HORIZONTAL) {
- p->mval[1] = p->mvali[1]; /* replace y */
- }
- else {
- p->mval[0] = p->mvali[0]; /* replace x */
- }
- break;
- }
- }
+ gpencil_speed_guide(p, guide);
}
else if (p->straight == STROKE_HORIZONTAL) {
p->mval[1] = p->mvali[1]; /* replace y */