diff options
Diffstat (limited to 'source/blender/editors/gpencil/gpencil_brush.c')
-rw-r--r-- | source/blender/editors/gpencil/gpencil_brush.c | 446 |
1 files changed, 223 insertions, 223 deletions
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c index 1cb882e9a43..c2e532be0b3 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)->location; 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)->location; 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; } @@ -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); |