diff options
Diffstat (limited to 'source/blender/editors/transform')
5 files changed, 282 insertions, 155 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 07ef6b9a819..9ad80f2ab12 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -44,6 +44,7 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ #include "DNA_workspace_types.h" +#include "DNA_gpencil_types.h" #include "BLI_alloca.h" #include "BLI_utildefines.h" @@ -85,6 +86,7 @@ #include "ED_mesh.h" #include "ED_clip.h" #include "ED_node.h" +#include "ED_gpencil.h" #include "WM_types.h" #include "WM_api.h" @@ -101,6 +103,8 @@ #include "transform.h" +#include "DEG_depsgraph.h" + /* Disabling, since when you type you know what you are doing, and being able to set it to zero is handy. */ // #define USE_NUM_NO_ZERO @@ -571,6 +575,10 @@ void removeAspectRatio(TransInfo *t, float vec[2]) static void viewRedrawForce(const bContext *C, TransInfo *t) { if (t->options & CTX_GPENCIL_STROKES) { + bGPdata *gpd = ED_gpencil_data_get_active(C); + if (gpd) { + DEG_id_tag_update(&gpd->id, OB_RECALC_DATA); + } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else if (t->spacetype == SPACE_VIEW3D) { @@ -1800,7 +1808,23 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) (float)t->mval[1], }; + +#if 0 /* XXX: Fix from 1c9690e7607bc990cc4a3e6ba839949bb83a78af cannot be used anymore */ + if ((t->flag & T_POINTS) && (t->options & CTX_GPENCIL_STROKES)) { + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + Object *ob = tc->obedit; + float vecrot[3]; + copy_v3_v3(vecrot, t->center); + mul_m4_v3(ob->obmat, vecrot); + projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO); + } + } + else { + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + } +#else projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); +#endif /* Offset the values for the area region. */ const float offset[2] = { @@ -3551,7 +3575,25 @@ static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, f else sub_v3_v3(vec, td->center); - mul_v3_fl(vec, td->factor); + /* grease pencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); + + /* scale stroke thickness */ + if (td->val) { + snapGridIncrement(t, t->values); + applyNumInput(&t->num, t->values); + + float ratio = t->values[0]; + *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; + CLAMP_MIN(*td->val, 0.001f); + } + + } + else { + mul_v3_fl(vec, td->factor); + } if (t->flag & (T_OBJECT | T_POSE)) { mul_m3_v3(td->smtx, vec); @@ -3905,6 +3947,20 @@ static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData * mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); + /* apply gpencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + float sx = smat[0][0]; + float sy = smat[1][1]; + float sz = smat[2][2]; + + mul_m3_fl(smat, gps->runtime.multi_frame_falloff); + /* fix scale */ + smat[0][0] = sx; + smat[1][1] = sy; + smat[2][2] = sz; + } + sub_v3_v3v3(vec, td->iloc, center); mul_m3_v3(smat, vec); @@ -4578,7 +4634,16 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) } mul_m3_v3(td->smtx, tvec); - mul_v3_fl(tvec, td->factor); + + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + /* proportional editing falloff */ + mul_v3_fl(tvec, td->factor); + } protectedTransBits(td->protectflag, tvec); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 675441189b0..d3b7417c4dd 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -90,6 +90,7 @@ #include "BKE_editmesh.h" #include "BKE_tracking.h" #include "BKE_mask.h" +#include "BKE_colortools.h" #include "BIK_api.h" @@ -3609,6 +3610,8 @@ static void posttrans_gpd_clean(bGPdata *gpd) } #endif } + /* set cache flag to dirty */ + DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA); } static void posttrans_mask_clean(Mask *mask) @@ -8086,7 +8089,14 @@ void flushTransPaintCurve(TransInfo *t) static void createTransGPencil(bContext *C, TransInfo *t) { + Depsgraph *depsgraph = CTX_data_depsgraph(C); \ bGPdata *gpd = ED_gpencil_data_get_active(C); + ToolSettings *ts = CTX_data_tool_settings(C); + + bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + bool use_multiframe_falloff = (ts->gp_sculpt.flag & GP_BRUSHEDIT_FLAG_FRAME_FALLOFF) != 0; + + Object *obact = CTX_data_active_object(C); bGPDlayer *gpl; TransData *td = NULL; float mtx[3][3], smtx[3][3]; @@ -8110,50 +8120,67 @@ static void createTransGPencil(bContext *C, TransInfo *t) if (gpd == NULL) return; + /* initialize falloff curve */ + if (is_multiedit) { + curvemapping_initialize(ts->gp_sculpt.cur_falloff); + } + /* First Pass: Count the number of datapoints required for the strokes, * (and additional info about the configuration - e.g. 2D/3D?) */ 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; + bGPDframe *gpf; bGPDstroke *gps; + bGPDframe *init_gpf = gpl->actframe; + if (is_multiedit) { + init_gpf = gpl->frames.first; + } - 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; - } + for (gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + 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(obact, gpl, gps) == false) { + continue; + } - if (is_prop_edit) { - /* Proportional Editing... */ - if (is_prop_edit_connected) { - /* connected only - so only if selected */ - if (gps->flag & GP_STROKE_SELECT) - tc->data_len += gps->totpoints; - } - else { - /* everything goes - connection status doesn't matter */ - tc->data_len += gps->totpoints; - } - } - else { - /* only selected stroke points are considered */ - if (gps->flag & GP_STROKE_SELECT) { - bGPDspoint *pt; - int i; - - // TODO: 2D vs 3D? - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->flag & GP_SPOINT_SELECT) - tc->data_len++; + if (is_prop_edit) { + /* Proportional Editing... */ + if (is_prop_edit_connected) { + /* connected only - so only if selected */ + if (gps->flag & GP_STROKE_SELECT) + tc->data_len += gps->totpoints; + } + else { + /* everything goes - connection status doesn't matter */ + tc->data_len += gps->totpoints; + } + } + else { + /* only selected stroke points are considered */ + if (gps->flag & GP_STROKE_SELECT) { + bGPDspoint *pt; + int i; + + // TODO: 2D vs 3D? + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->flag & GP_SPOINT_SELECT) + tc->data_len++; + } + } } } } + /* if not multiedit out of loop */ + if (!is_multiedit) { + break; + } } } } @@ -8180,153 +8207,166 @@ static void createTransGPencil(bContext *C, TransInfo *t) float diff_mat[4][4]; float inverse_diff_mat[4][4]; - /* calculate difference matrix if parent object */ - if (gpl->parent != NULL) { - ED_gpencil_parent_location(gpl, diff_mat); - /* undo matrix */ - invert_m4_m4(inverse_diff_mat, diff_mat); + bGPDframe *init_gpf = gpl->actframe; + if (is_multiedit) { + init_gpf = gpl->frames.first; } + /* init multiframe falloff options */ + int f_init = 0; + int f_end = 0; + + if (use_multiframe_falloff) { + BKE_gpencil_get_range_selected(gpl, &f_init, &f_end); + } + + /* calculate difference matrix */ + ED_gpencil_parent_location(depsgraph, obact, gpd, gpl, diff_mat); + /* undo matrix */ + invert_m4_m4(inverse_diff_mat, diff_mat); /* 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... */ - if (gpf->framenum != cfra) { + // XXX: should this be allowed when framelock is enabled? + if ((gpf->framenum != cfra) && (!is_multiedit)) { gpf = BKE_gpencil_frame_addcopy(gpl, cfra); /* in some weird situations (framelock enabled) return NULL */ if (gpf == NULL) { continue; } + if (!is_multiedit) { + init_gpf = gpf; + } } /* Loop over strokes, adding TransData for points as needed... */ - for (gps = gpf->strokes.first; gps; gps = gps->next) { - TransData *head = td; - TransData *tail = td; - bool stroke_ok; - - /* 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; - } - /* What we need to include depends on proportional editing settings... */ - if (is_prop_edit) { - if (is_prop_edit_connected) { - /* A) "Connected" - Only those in selected strokes */ - stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; - } - else { - /* B) All points, always */ - stroke_ok = true; - } - } - else { - /* C) Only selected points in selected strokes */ - stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; - } - - /* Do stroke... */ - if (stroke_ok && gps->totpoints) { - bGPDspoint *pt; - int i; - -#if 0 /* XXX: this isn't needed anymore; cannot calculate center this way or is_prop_edit breaks */ - const float ninv = 1.0f / gps->totpoints; - float center[3] = {0.0f}; - - /* compute midpoint of stroke */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - madd_v3_v3v3fl(center, center, &pt->x, ninv); + for (gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + + /* if multiframe and falloff, recalculate and save value */ + float falloff = 1.0f; /* by default no falloff */ + if ((is_multiedit) && (use_multiframe_falloff)) { + /* Faloff depends on distance to active frame (relative to the overall frame range) */ + falloff = BKE_gpencil_multiframe_falloff_calc(gpf, gpl->actframe->framenum, + f_init, f_end, ts->gp_sculpt.cur_falloff); } -#endif - /* add all necessary points... */ - for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - bool point_ok; + for (gps = gpf->strokes.first; gps; gps = gps->next) { + TransData *head = td; + TransData *tail = td; + bool stroke_ok; - /* include point? */ + /* 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(obact, gpl, gps) == false) { + continue; + } + /* What we need to include depends on proportional editing settings... */ if (is_prop_edit) { - /* Always all points in strokes that get included */ - point_ok = true; + if (is_prop_edit_connected) { + /* A) "Connected" - Only those in selected strokes */ + stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; + } + else { + /* B) All points, always */ + stroke_ok = true; + } } else { - /* Only selected points in selected strokes */ - point_ok = (pt->flag & GP_SPOINT_SELECT) != 0; + /* C) Only selected points in selected strokes */ + stroke_ok = (gps->flag & GP_STROKE_SELECT) != 0; } - /* do point... */ - if (point_ok) { - copy_v3_v3(td->iloc, &pt->x); - copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local? - - td->loc = &pt->x; - - td->flag = 0; + /* Do stroke... */ + if (stroke_ok && gps->totpoints) { + bGPDspoint *pt; + int i; - if (pt->flag & GP_SPOINT_SELECT) - td->flag |= TD_SELECTED; - - /* for other transform modes (e.g. shrink-fatten), need to additional data */ - if (t->mode == TFM_GPENCIL_SHRINKFATTEN) { - td->val = &pt->pressure; - td->ival = pt->pressure; - } + /* save falloff factor */ + gps->runtime.multi_frame_falloff = falloff; - /* screenspace needs special matrices... */ - if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) { - /* screenspace */ - td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; + /* add all necessary points... */ + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + bool point_ok; - /* apply parent transformations */ - if (gpl->parent == NULL) { - copy_m3_m4(td->smtx, t->persmat); - copy_m3_m4(td->mtx, t->persinv); - unit_m3(td->axismtx); + /* include point? */ + if (is_prop_edit) { + /* Always all points in strokes that get included */ + point_ok = true; } else { - /* apply matrix transformation relative to parent */ - copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ - copy_m3_m4(td->mtx, diff_mat); /* display position */ - copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ - } - } - else { - /* configure 2D dataspace points so that they don't play up... */ - if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) { - td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; - // XXX: matrices may need to be different? + /* Only selected points in selected strokes */ + point_ok = (pt->flag & GP_SPOINT_SELECT) != 0; } - /* apply parent transformations */ - if (gpl->parent == NULL) { - copy_m3_m3(td->smtx, smtx); - copy_m3_m3(td->mtx, mtx); - unit_m3(td->axismtx); // XXX? - } - else { - /* apply matrix transformation relative to parent */ - copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ - copy_m3_m4(td->mtx, diff_mat); /* display position */ - copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ + /* do point... */ + if (point_ok) { + copy_v3_v3(td->iloc, &pt->x); + copy_v3_v3(td->center, &pt->x); // XXX: what about t->around == local? + + td->loc = &pt->x; + + td->flag = 0; + + if (pt->flag & GP_SPOINT_SELECT) + td->flag |= TD_SELECTED; + + /* for other transform modes (e.g. shrink-fatten), need to additional data + * but never for scale or mirror + */ + if ((t->mode != TFM_RESIZE) && (t->mode != TFM_MIRROR)) { + td->val = &pt->pressure; + td->ival = pt->pressure; + } + + /* screenspace needs special matrices... */ + if ((gps->flag & (GP_STROKE_3DSPACE | GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) == 0) { + /* screenspace */ + td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; + + /* apply matrix transformation relative to parent */ + copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ + copy_m3_m4(td->mtx, diff_mat); /* display position */ + copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ + } + else { + /* configure 2D dataspace points so that they don't play up... */ + if (gps->flag & (GP_STROKE_2DSPACE | GP_STROKE_2DIMAGE)) { + td->protectflag = OB_LOCK_LOCZ | OB_LOCK_ROTZ | OB_LOCK_SCALEZ; + // XXX: matrices may need to be different? + } + + /* apply parent transformations */ + copy_m3_m4(td->smtx, inverse_diff_mat); /* final position */ + copy_m3_m4(td->mtx, diff_mat); /* display position */ + copy_m3_m4(td->axismtx, diff_mat); /* axis orientation */ + } + /* Triangulation must be calculated again, so save the stroke for recalc function */ + td->extra = gps; + + /* save pointer to object */ + td->ob = obact; + + td++; + tail++; } } - /* Triangulation must be calculated again, so save the stroke for recalc function */ - td->extra = gps; - td++; - tail++; + /* March over these points, and calculate the proportional editing distances */ + if (is_prop_edit && (head != tail)) { + /* XXX: for now, we are similar enough that this works... */ + calc_distanceCurveVerts(head, tail - 1); + } } } - - /* March over these points, and calculate the proportional editing distances */ - if (is_prop_edit && (head != tail)) { - /* XXX: for now, we are similar enough that this works... */ - calc_distanceCurveVerts(head, tail - 1); - } + } + /* if not multiedit out of loop */ + if (!is_multiedit) { + break; } } } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 3618d57b3ed..a2377166dff 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -74,6 +74,7 @@ #include "BKE_armature.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_gpencil.h" #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_main.h" @@ -105,6 +106,7 @@ #include "ED_curve.h" /* for curve_editnurbs */ #include "ED_clip.h" #include "ED_screen.h" +#include "ED_gpencil.h" #include "WM_types.h" #include "WM_api.h" @@ -379,7 +381,8 @@ static void recalcData_actedit(TransInfo *t) /* flush transform values back to actual coordinates */ flushTransIntFrameActionData(t); } - else { + + if (ac.datatype != ANIMCONT_MASK) { /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_ANIMDATA); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); @@ -1311,7 +1314,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } /* GPencil editing context */ - if ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)) { + if (GPENCIL_ANY_MODE(gpd)) { t->options |= CTX_GPENCIL_STROKES; } @@ -1823,6 +1826,21 @@ void calculateCenterCursor(TransInfo *t, float r_center[3]) } r_center[2] = 0.0f; } + else if (t->options & CTX_GPENCIL_STROKES) { + /* move cursor in local space */ + TransData *td = NULL; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + float mat[3][3], imat[3][3]; + + td = tc->data; + Object *ob = td->ob; + + sub_v3_v3v3(r_center, r_center, ob->obmat[3]); + copy_m3_m4(mat, ob->obmat); + invert_m3_m3(imat, mat); + mul_m3_v3(imat, r_center); + } + } } void calculateCenterCursor2D(TransInfo *t, float r_center[2]) diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index cbc2b312512..3b5d7d5871a 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -604,6 +604,7 @@ int ED_transform_calc_gizmo_stats( ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); + Depsgraph *depsgraph = CTX_data_depsgraph(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *obedit = CTX_data_edit_object(C); View3D *v3d = sa->spacedata.first; @@ -611,7 +612,7 @@ int ED_transform_calc_gizmo_stats( Base *base; Object *ob = OBACT(view_layer); bGPdata *gpd = CTX_data_gpencil_data(C); - const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE)); + const bool is_gp_edit = GPENCIL_ANY_MODE(gpd); int a, totsel = 0; const int pivot_point = scene->toolsettings->transform_pivot_point; @@ -728,10 +729,8 @@ int ED_transform_calc_gizmo_stats( /* only editable and visible layers are considered */ if (gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { - /* calculate difference matrix if parent object */ - if (gpl->parent != NULL) { - ED_gpencil_parent_location(gpl, diff_mat); - } + /* calculate difference matrix */ + ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, diff_mat); for (bGPDstroke *gps = gpl->actframe->strokes.first; gps; gps = gps->next) { /* skip strokes that are invalid for current view */ diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index a6e857c4a60..bc35e6e6b89 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -2280,7 +2280,12 @@ static short snapObject( dist_px, r_loc, r_no, r_index); break; - + case OB_GPENCIL: + retval = snapEmpty( + snapdata, ob, obmat, + dist_px, + r_loc, r_no, r_index); + break; case OB_CAMERA: retval = snapCamera( sctx, snapdata, ob, obmat, |