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:
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_brush.c')
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c403
1 files changed, 277 insertions, 126 deletions
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 0271afd6827..fcb2ce02bde 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -18,7 +18,7 @@
* The Original Code is Copyright (C) 2015, Blender Foundation
* This is a new part of Blender
*
- * Contributor(s): Joshua Leung
+ * Contributor(s): Joshua Leung, Antonio Vazquez
*
* ***** END GPL LICENSE BLOCK *****
*
@@ -51,6 +51,7 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_object_types.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -223,9 +224,26 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso, bGPDstroke *gps, int i
GP_EditBrush_Data *brush = gso->brush;
float inf = gp_brush_influence_calc(gso, radius, co);
bool affect_pressure = (brush->flag & GP_EDITBRUSH_FLAG_SMOOTH_PRESSURE) != 0;
-
+ /* need one flag enabled by default */
+ if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
+ GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
+ GP_BRUSHEDIT_FLAG_APPLY_THICKNESS)) == 0)
+ {
+ gso->settings->flag |= GP_BRUSHEDIT_FLAG_APPLY_POSITION;
+ }
+
/* perform smoothing */
- return gp_smooth_stroke(gps, i, inf, affect_pressure);
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_POSITION) {
+ gp_smooth_stroke(gps, i, inf, affect_pressure);
+ }
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_STRENGTH) {
+ gp_smooth_stroke_strength(gps, i, inf);
+ }
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) {
+ gp_smooth_stroke_thickness(gps, i, inf);
+ }
+
+ return true;
}
/* ----------------------------------------------- */
@@ -268,6 +286,41 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
/* ----------------------------------------------- */
+/* Color Strength Brush */
+
+/* Make color more or less transparent by the specified amounts */
+static bool gp_brush_strength_apply(
+ tGP_BrushEditData *gso, bGPDstroke *gps, int i,
+ const int radius, const int co[2])
+{
+ 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)) {
+ /* make line thinner - reduce stroke pressure */
+ pt->strength -= inf;
+ }
+ else {
+ /* make line thicker - increase stroke pressure */
+ pt->strength += inf;
+ }
+
+ /* Strength should stay within [0.0, 1.0] */
+ CLAMP(pt->strength, 0.0f, 1.0f);
+
+ return true;
+}
+
+
+/* ----------------------------------------------- */
/* Grab Brush */
/* Custom data per stroke for the Grab Brush
@@ -373,11 +426,12 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso)
}
/* Apply grab transform to all relevant points of the affected strokes */
-static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, bGPDstroke *gps)
+static void gp_brush_grab_apply_cached(
+ tGP_BrushEditData *gso, bGPDstroke *gps, bool parented, float diff_mat[4][4])
{
tGPSB_Grab_StrokeData *data = BLI_ghash_lookup(gso->stroke_customdata, gps);
int i;
-
+
/* Apply dvec to all of the stored points */
for (i = 0; i < data->size; i++) {
bGPDspoint *pt = &gps->points[data->points[i]];
@@ -385,9 +439,23 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso, bGPDstroke *gps)
/* adjust the amount of displacement to apply */
mul_v3_v3fl(delta, gso->dvec, data->weights[i]);
+ if (!parented) {
+ /* apply */
+ add_v3_v3(&pt->x, delta);
+ }
+ else {
+ float fpt[3];
+ /* apply transformation */
+ mul_v3_m4v3(fpt, diff_mat, &pt->x);
+ /* apply */
+ add_v3_v3(fpt, delta);
+ copy_v3_v3(&pt->x, fpt);
+ /* undo transformation to the init parent position */
+ float inverse_diff_mat[4][4];
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+ mul_m4_v3(inverse_diff_mat, &pt->x);
+ }
- /* apply */
- add_v3_v3(&pt->x, delta);
}
}
@@ -592,62 +660,92 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso, bGPDstroke *gps, in
*/
const float inf = gp_brush_influence_calc(gso, radius, co) / 2.0f;
const float fac = BLI_frand() * inf;
-
- /* Jitter is applied perpendicular to the mouse movement vector
- * - We compute all effects in screenspace (since it's easier)
- * and then project these to get the points/distances in
- * viewspace as needed
- */
- float mvec[2], svec[2];
-
- /* mouse movement in ints -> floats */
- mvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
- mvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
-
- /* rotate mvec by 90 degrees... */
- svec[0] = -mvec[1];
- svec[1] = mvec[0];
-
- //printf("svec = %f %f, ", svec[0], svec[1]);
-
- /* scale the displacement by the random displacement, and apply */
- if (BLI_frand() > 0.5f) {
- mul_v2_fl(svec, -fac);
- }
- else {
- mul_v2_fl(svec, fac);
+ /* need one flag enabled by default */
+ if ((gso->settings->flag & (GP_BRUSHEDIT_FLAG_APPLY_POSITION |
+ GP_BRUSHEDIT_FLAG_APPLY_STRENGTH |
+ GP_BRUSHEDIT_FLAG_APPLY_THICKNESS)) == 0)
+ {
+ gso->settings->flag |= GP_BRUSHEDIT_FLAG_APPLY_POSITION;
}
-
- //printf("%f %f (%f), nco = {%f %f}, co = %d %d\n", svec[0], svec[1], fac, nco[0], nco[1], co[0], co[1]);
-
- /* convert to dataspace */
- if (gps->flag & GP_STROKE_3DSPACE) {
- /* 3D: Project to 3D space */
- if (gso->sa->spacetype == SPACE_VIEW3D) {
- bool flip;
- RegionView3D *rv3d = gso->ar->regiondata;
- float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip);
- if (flip == false) {
- float dvec[3];
- ED_view3d_win_to_delta(gso->gsc.ar, svec, dvec, zfac);
- add_v3_v3(&pt->x, dvec);
+
+ /* apply random to position */
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_POSITION) {
+ /* Jitter is applied perpendicular to the mouse movement vector
+ * - We compute all effects in screenspace (since it's easier)
+ * and then project these to get the points/distances in
+ * viewspace as needed
+ */
+ float mvec[2], svec[2];
+
+ /* mouse movement in ints -> floats */
+ mvec[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
+ mvec[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
+
+ /* rotate mvec by 90 degrees... */
+ svec[0] = -mvec[1];
+ svec[1] = mvec[0];
+
+ /* scale the displacement by the random displacement, and apply */
+ if (BLI_frand() > 0.5f) {
+ mul_v2_fl(svec, -fac);
+ }
+ else {
+ mul_v2_fl(svec, fac);
+ }
+
+ //printf("%f %f (%f), nco = {%f %f}, co = %d %d\n", svec[0], svec[1], fac, nco[0], nco[1], co[0], co[1]);
+
+ /* convert to dataspace */
+ if (gps->flag & GP_STROKE_3DSPACE) {
+ /* 3D: Project to 3D space */
+ if (gso->sa->spacetype == SPACE_VIEW3D) {
+ bool flip;
+ RegionView3D *rv3d = gso->ar->regiondata;
+ float zfac = ED_view3d_calc_zfac(rv3d, &pt->x, &flip);
+ if (flip == false) {
+ float dvec[3];
+ ED_view3d_win_to_delta(gso->gsc.ar, svec, dvec, zfac);
+ add_v3_v3(&pt->x, dvec);
+ }
+ }
+ else {
+ /* ERROR */
+ BLI_assert("3D stroke being sculpted in non-3D view");
}
}
else {
- /* ERROR */
- BLI_assert("3D stroke being sculpted in non-3D view");
+ /* 2D: As-is */
+ // XXX: v2d scaling/offset?
+ float nco[2];
+ nco[0] = (float)co[0] + svec[0];
+ nco[1] = (float)co[1] + svec[1];
+
+ copy_v2_v2(&pt->x, nco);
}
}
- else {
- /* 2D: As-is */
- // XXX: v2d scaling/offset?
- float nco[2];
- nco[0] = (float)co[0] + svec[0];
- nco[1] = (float)co[1] + svec[1];
-
- copy_v2_v2(&pt->x, nco);
+ /* apply random to strength */
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_STRENGTH) {
+ if (BLI_frand() > 0.5f) {
+ pt->strength += fac;
+ }
+ else {
+ pt->strength -= fac;
+ }
+ CLAMP_MIN(pt->strength, 0.0f);
+ CLAMP_MAX(pt->strength, 1.0f);
}
-
+ /* apply random to thickness (use pressure) */
+ if (gso->settings->flag & GP_BRUSHEDIT_FLAG_APPLY_THICKNESS) {
+ if (BLI_frand() > 0.5f) {
+ pt->pressure += fac;
+ }
+ else {
+ pt->pressure -= fac;
+ }
+ /* only limit lower value */
+ CLAMP_MIN(pt->pressure, 0.0f);
+ }
+
/* done */
return true;
}
@@ -743,7 +841,7 @@ static void gp_brush_clone_add(bContext *C, tGP_BrushEditData *gso)
Scene *scene = gso->scene;
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
- bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, true);
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, true);
bGPDstroke *gps;
float delta[3];
@@ -1087,7 +1185,7 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
*/
// XXX: should this be allowed when framelock is enabled?
if (gpf->framenum != cfra) {
- gpencil_frame_addcopy(gpl, cfra);
+ BKE_gpencil_frame_addcopy(gpl, cfra);
}
}
}
@@ -1099,7 +1197,9 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
/* Apply ----------------------------------------------- */
/* Apply brush operation to points in this stroke */
-static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, bGPDstroke *gps, GP_BrushApplyCb apply)
+static bool gpsculpt_brush_do_stroke(
+ tGP_BrushEditData *gso, bGPDstroke *gps, bool parented,
+ float diff_mat[4][4], GP_BrushApplyCb apply)
{
GP_SpaceConversion *gsc = &gso->gsc;
rcti *rect = &gso->brush_rect;
@@ -1111,9 +1211,16 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, bGPDstroke *gps, GP
int i;
bool include_last = false;
bool changed = false;
-
+
if (gps->totpoints == 1) {
- gp_point_to_xy(gsc, gps, gps->points, &pc1[0], &pc1[1]);
+ if (!parented) {
+ gp_point_to_xy(gsc, gps, gps->points, &pc1[0], &pc1[1]);
+ }
+ else {
+ bGPDspoint pt_temp;
+ 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])) {
@@ -1140,10 +1247,20 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso, bGPDstroke *gps, GP
continue;
}
}
-
- gp_point_to_xy(gsc, gps, pt1, &pc1[0], &pc1[1]);
- gp_point_to_xy(gsc, gps, pt2, &pc2[0], &pc2[1]);
-
+ if (!parented) {
+ gp_point_to_xy(gsc, gps, pt1, &pc1[0], &pc1[1]);
+ gp_point_to_xy(gsc, gps, pt2, &pc2[0], &pc2[1]);
+ }
+ else {
+ bGPDspoint npt;
+ gp_point_to_parent_space(pt1, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc1[0], &pc1[1]);
+
+ gp_point_to_parent_space(pt2, diff_mat, &npt);
+ gp_point_to_xy(gsc, gps, &npt, &pc2[0], &pc2[1]);
+ }
+
+
/* Check that point segment of the boundbox of the selection stroke */
if (((!ELEM(V2D_IS_CLIPPED, pc1[0], pc1[1])) && BLI_rcti_isect_pt(rect, pc1[0], pc1[1])) ||
((!ELEM(V2D_IS_CLIPPED, pc2[0], pc2[1])) && BLI_rcti_isect_pt(rect, pc2[0], pc2[1])))
@@ -1228,76 +1345,105 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
/* Find visible strokes, and perform operations on those if hit */
- CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+ float diff_mat[4][4];
+ bool parented = false;
+
+ CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
{
- switch (gso->brush_type) {
- case GP_EDITBRUSH_TYPE_SMOOTH: /* Smooth strokes */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_smooth_apply);
- break;
- }
-
- case GP_EDITBRUSH_TYPE_THICKNESS: /* Adjust stroke thickness */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_thickness_apply);
- break;
+ /* calculate difference matrix if parent object */
+ if (gpl->parent != NULL) {
+ ED_gpencil_parent_location(gpl, diff_mat);
+ parented = true;
+ }
+ else {
+ parented = false;
+ }
+
+ bGPDframe *gpf = gpl->actframe;
+ bGPDstroke *gps;
+ 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;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps) == false) {
+ continue;
}
-
- case GP_EDITBRUSH_TYPE_GRAB: /* Grab points */
- {
- if (gso->first) {
- /* First time this brush stroke is being applied:
- * 1) Prepare data buffers (init/clear) for this stroke
- * 2) Use the points now under the cursor
- */
- gp_brush_grab_stroke_init(gso, gps);
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_grab_store_points);
+
+ switch (gso->brush_type) {
+ case GP_EDITBRUSH_TYPE_SMOOTH: /* Smooth strokes */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_smooth_apply);
+ break;
}
- else {
- /* Apply effect to the stored points */
- gp_brush_grab_apply_cached(gso, gps);
- changed |= true;
+
+ case GP_EDITBRUSH_TYPE_THICKNESS: /* Adjust stroke thickness */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_thickness_apply);
+ break;
}
- break;
- }
-
- case GP_EDITBRUSH_TYPE_PUSH: /* Push points */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_push_apply);
- break;
- }
-
- case GP_EDITBRUSH_TYPE_PINCH: /* Pinch points */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_pinch_apply);
- break;
- }
-
- case GP_EDITBRUSH_TYPE_TWIST: /* Twist points around midpoint */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_twist_apply);
- break;
+
+ case GP_EDITBRUSH_TYPE_STRENGTH: /* Adjust stroke color strength */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_strength_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_GRAB: /* Grab points */
+ {
+ if (gso->first) {
+ /* First time this brush stroke is being applied:
+ * 1) Prepare data buffers (init/clear) for this stroke
+ * 2) Use the points now under the cursor
+ */
+ gp_brush_grab_stroke_init(gso, gps);
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_grab_store_points);
+ }
+ else {
+ /* Apply effect to the stored points */
+ gp_brush_grab_apply_cached(gso, gps, parented, diff_mat);
+ changed |= true;
+ }
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_PUSH: /* Push points */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_push_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_PINCH: /* Pinch points */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_pinch_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_TWIST: /* Twist points around midpoint */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_twist_apply);
+ break;
+ }
+
+ case GP_EDITBRUSH_TYPE_RANDOMIZE: /* Apply jitter */
+ {
+ changed |= gpsculpt_brush_do_stroke(gso, gps, parented, diff_mat, gp_brush_randomize_apply);
+ break;
+ }
+
+ default:
+ printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
+ break;
}
-
- case GP_EDITBRUSH_TYPE_RANDOMIZE: /* Apply jitter */
- {
- changed |= gpsculpt_brush_do_stroke(gso, gps, gp_brush_randomize_apply);
- break;
+ /* Triangulation must be calculated if changed */
+ if (changed) {
+ gps->flag |= GP_STROKE_RECALC_CACHES;
+ gps->tot_triangles = 0;
}
-
- default:
- printf("ERROR: Unknown type of GPencil Sculpt brush - %u\n", gso->brush_type);
- break;
- }
-
- /* Triangulation must be calculated if changed */
- if (changed) {
- gps->flag |= GP_STROKE_RECALC_CACHES;
- gps->tot_triangles = 0;
}
}
CTX_DATA_END;
-
+
return changed;
}
@@ -1441,6 +1587,11 @@ static int gpsculpt_brush_invoke(bContext *C, wmOperator *op, const wmEvent *eve
needs_timer = true;
break;
+ case GP_EDITBRUSH_TYPE_STRENGTH:
+ brush_rate = 0.01f; // XXX: hardcoded
+ needs_timer = true;
+ break;
+
case GP_EDITBRUSH_TYPE_PINCH:
brush_rate = 0.001f; // XXX: hardcoded
needs_timer = true;