diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2021-01-16 17:33:38 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2021-01-16 17:46:45 +0300 |
commit | e02d84eb3bea710aa4a658629813bd7e4c67ce4c (patch) | |
tree | 96411e6b1d1d35d6169f5e903f5f18422e1dbd99 /source | |
parent | 0a44c4b5942e9bcad2269bd4a1339bac462728e0 (diff) |
GPencil: Add new parameteres to transform layers
When using grease pencil for drawing Storyboards, it's very common to require a transform of the layers. This transform can be done using the offset modifier, but in some cases, the scene requires a lot of modifiers and makes the file hard to work.
This new feature adds a transforms Location, Rotation and Scale at Layer level, and allows to transform the layer without using a modifier, keeping the scene more clean.
{F9480695}
This feature was suggested by @pepeland after receiving feedback from several artists.
Also, done some code cleanup and rename some functions to get a better naming.
Maniphest Tasks: T83660
Differential Revision: https://developer.blender.org/D9761
Diffstat (limited to 'source')
24 files changed, 306 insertions, 101 deletions
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index df5711f5120..8903abee432 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -280,12 +280,12 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig const struct bGPDframe *gpf_eval); void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval); -void BKE_gpencil_parent_matrix_get(const struct Depsgraph *depsgraph, - struct Object *obact, - struct bGPDlayer *gpl, - float diff_mat[4][4]); +void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, + struct Object *obact, + struct bGPDlayer *gpl, + float diff_mat[4][4]); -void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct Object *ob); +void BKE_gpencil_update_layer_transforms(const struct Depsgraph *depsgraph, struct Object *ob); int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char *name_prefix); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index c7ca82c92fc..83b20e602c3 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -95,6 +95,32 @@ static void greasepencil_copy_data(Main *UNUSED(bmain), /* TODO here too could add unused flags... */ bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); + /* Apply local layer transform to all frames. Calc the active frame is not enough + * because onion skin can use more frames. This is more slow but required here. */ + if (gpl_dst->actframe != NULL) { + bool transfomed = ((!is_zero_v3(gpl_dst->location)) || (!is_zero_v3(gpl_dst->rotation)) || + (!is_one_v3(gpl_dst->scale))); + if (transfomed) { + loc_eul_size_to_mat4( + gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale); + bool do_onion = ((gpl_dst->onion_flag & GP_LAYER_ONIONSKIN) != 0); + bGPDframe *init_gpf = (do_onion) ? gpl_dst->frames.first : gpl_dst->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + mul_m4_v3(gpl_dst->layer_mat, &pt->x); + } + } + /* if not onion, exit loop. */ + if (!do_onion) { + break; + } + } + } + } + BLI_addtail(&gpd_dst->layers, gpl_dst); } } @@ -686,6 +712,14 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti /* Enable always affected by scene lights. */ gpl->flag |= GP_LAYER_USE_LIGHTS; + + /* Init transform. */ + zero_v3(gpl->location); + zero_v3(gpl->rotation); + copy_v3_fl(gpl->scale, 1.0f); + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* make this one the active one */ if (setactive) { BKE_gpencil_layer_active_set(gpd, gpl); @@ -2759,10 +2793,10 @@ void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_ev * \param gpl: Grease pencil layer * \param diff_mat: Result parent matrix */ -void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, - Object *obact, - bGPDlayer *gpl, - float diff_mat[4][4]) +void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, + Object *obact, + bGPDlayer *gpl, + float diff_mat[4][4]) { Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; Object *obparent = gpl->parent; @@ -2771,11 +2805,10 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, /* if not layer parented, try with object parented */ if (obparent_eval == NULL) { - if (ob_eval != NULL) { - if (ob_eval->type == OB_GPENCIL) { - copy_m4_m4(diff_mat, ob_eval->obmat); - return; - } + if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) { + copy_m4_m4(diff_mat, ob_eval->obmat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); + return; } /* not gpencil object */ unit_m4(diff_mat); @@ -2785,6 +2818,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } if (gpl->partype == PARBONE) { @@ -2800,6 +2834,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); } + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } @@ -2807,11 +2842,11 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, } /** - * Update parent matrix. + * Update parent matrix and local transforms. * \param depsgraph: Depsgraph * \param ob: Grease pencil object */ -void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) +void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob) { if (ob->type != OB_GPENCIL) { return; @@ -2820,31 +2855,50 @@ void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) bGPdata *gpd = (bGPdata *)ob->data; float cur_mat[4][4]; + bool changed = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if ((gpl->parent != NULL) && (gpl->actframe != NULL)) { - Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); - /* calculate new matrix */ - if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - copy_m4_m4(cur_mat, ob_parent->obmat); - } - else if (gpl->partype == PARBONE) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); - if (pchan != NULL) { - copy_m4_m4(cur_mat, ob->imat); - mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); + unit_m4(cur_mat); + if (gpl->actframe != NULL) { + if (gpl->parent != NULL) { + Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); + /* calculate new matrix */ + if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { + copy_m4_m4(cur_mat, ob_parent->obmat); } - else { - unit_m4(cur_mat); + else if (gpl->partype == PARBONE) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); + if (pchan != NULL) { + copy_m4_m4(cur_mat, ob->imat); + mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); + } + else { + unit_m4(cur_mat); + } } + changed = !equals_m4m4(gpl->inverse, cur_mat); } + + /* Calc local layer transform. */ + bool transfomed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || + (!is_one_v3(gpl->scale))); + if (transfomed) { + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + } + /* only redo if any change */ - if (!equals_m4m4(gpl->inverse, cur_mat)) { + if (changed || transfomed) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { bGPDspoint *pt; int i; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - mul_m4_v3(gpl->inverse, &pt->x); - mul_m4_v3(cur_mat, &pt->x); + if (changed) { + mul_m4_v3(gpl->inverse, &pt->x); + mul_m4_v3(cur_mat, &pt->x); + } + + if (transfomed) { + mul_m4_v3(gpl->layer_mat, &pt->x); + } } } } diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 1be2cba31b5..8b12e1b5fca 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -701,13 +701,18 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o Object *ob_orig = (Object *)DEG_get_original_id(&ob->id); bGPdata *gpd_orig = (bGPdata *)ob_orig->data; - /* Need check if some layer is parented. */ + /* Need check if some layer is parented or transformed. */ bool do_parent = false; + bool do_transform = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) { if (gpl->parent != NULL) { do_parent = true; break; } + if ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || (!is_one_v3(gpl->scale))) { + do_transform = true; + break; + } } const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval); @@ -715,7 +720,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) && (ob->greasepencil_modifiers.first != NULL) && (!GPENCIL_SIMPLIFY_MODIF(scene))); - if ((!do_modifiers) && (!do_parent)) { + if ((!do_modifiers) && (!do_parent) && (!do_transform)) { return; } DEG_debug_print_eval(depsgraph, __func__, gpd_eval->id.name, gpd_eval); diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 1d79f871fa2..69442b7646c 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -225,7 +225,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o case OB_GPENCIL: { BKE_gpencil_prepare_eval_data(depsgraph, scene, ob); BKE_gpencil_modifiers_calc(depsgraph, scene, ob); - BKE_gpencil_update_layer_parent(depsgraph, ob); + BKE_gpencil_update_layer_transforms(depsgraph, ob); break; } case OB_HAIR: diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 49c8947dd04..40481505e1c 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1582,5 +1582,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) */ { /* Keep this block, even when empty. */ + + /* Grease pencil layer transform matrix. */ + if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "float", "location[0]")) { + LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) { + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + zero_v3(gpl->location); + zero_v3(gpl->rotation); + copy_v3_fl(gpl->scale, 1.0f); + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + } + } + } } } diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c index 7f9290a6c3a..19af3ae7e5d 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.c +++ b/source/blender/draw/engines/overlay/overlay_gpencil.c @@ -258,6 +258,16 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) copy_m4_m4(mat, ob->obmat); + /* Rotate and scale except align to cursor. */ + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + if (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR) { + float matrot[3][3]; + copy_m3_m4(matrot, gpl->layer_mat); + mul_m4_m4m3(mat, mat, matrot); + } + } + float viewinv[4][4]; /* Set the grid in the selected axis */ switch (ts->gp_sculpt.lock_axis) { @@ -294,6 +304,11 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) mul_v2_v2fl(size, gpd->grid.scale, 2.0f * ED_scene_grid_scale(scene, &grid_unit)); rescale_m4(mat, (float[3]){size[0], size[1], 0.0f}); + /* Apply layer loc transform, except cursor mode. */ + if ((gpl != NULL) && (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + add_v3_v3(mat[3], gpl->layer_mat[3]); + } + const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines; int line_ct = gridlines * 4 + 2; diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index e1523db36c7..8feacf8b026 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -800,20 +800,20 @@ static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl, }; /* First segment. */ - copy_v3_v3(vert_ptr->pos, bezt->vec[0]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[0]); vert_ptr->data = vflag[0]; vert_ptr++; - copy_v3_v3(vert_ptr->pos, bezt->vec[1]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); vert_ptr->data = vflag[1]; vert_ptr++; /* Second segment. */ - copy_v3_v3(vert_ptr->pos, bezt->vec[1]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); vert_ptr->data = vflag[1]; vert_ptr++; - copy_v3_v3(vert_ptr->pos, bezt->vec[2]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[2]); vert_ptr->data = vflag[2]; vert_ptr++; } diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 09b57029350..22a628de8b1 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -178,7 +178,7 @@ static void gpencil_strokepoint_convertcoords(bContext *C, /* apply parent transform */ float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); mul_v3_m4v3(fpt, diff_mat, &source_pt->x); copy_v3_v3(&pt->x, fpt); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index ad9b72b713e..7eac4af0cba 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -2854,7 +2854,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) float inverse_diff_mat[4][4]; /* recalculate all stroke points */ - BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat); Material *ma_src = NULL; diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d1c8eca1be0..9628790f27e 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -2800,7 +2800,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) float diff_mat[4][4]; /* calculate difference matrix object */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -2935,7 +2935,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -3039,7 +3039,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 6d349bd2dd4..84447059884 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -263,14 +263,14 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) BLI_assert(gpl_active_index >= 0); LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate parent position */ - BKE_gpencil_parent_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); - /* do not draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) { continue; } + /* calculate parent position */ + BKE_gpencil_layer_transform_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); + /* Decide if the strokes of layers are included or not depending on the layer mode. * Cannot skip the layer because it can use boundary strokes and must be used. */ bool skip = false; @@ -1275,7 +1275,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) float origin[3]; ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1); + tgpf->scene, tgpf->ob, tgpf->rv3d, tgpf->gpl, gps, origin, tgpf->lock_axis - 1); } /* if parented change position relative to parent object */ diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 4a908eff92e..4c554be1cc4 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -667,7 +667,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -718,7 +719,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -767,8 +769,10 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ - invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + /* Undo layer transform. */ \ + mul_m4_m4m4(gpstroke_iter.diff_mat, gpstroke_iter.diff_mat, gpl->layer_invmat); \ /* loop over strokes */ \ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_->strokes) { \ /* skip strokes that are invalid for current view */ \ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 14313a50118..fd965f09de0 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -426,7 +426,7 @@ static void gpencil_reproject_toplane(tGPsdata *p, bGPDstroke *gps) /* get drawing origin */ gpencil_get_3d_reference(p, origin); - ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1); + ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, p->gpl, gps, origin, p->lock_axis - 1); } /* convert screen-coordinates to buffer-coordinates */ @@ -887,11 +887,13 @@ static short gpencil_stroke_addpoint(tGPsdata *p, gpencil_get_3d_reference(p, origin); /* reproject current */ ED_gpencil_tpoint_to_point(p->region, origin, pt, &spt); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(p->region, origin, ptb, &spt2); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt2); p->totpixlen += len_v3v3(&spt.x, &spt2.x); pt->uv_fac = p->totpixlen; } @@ -1349,7 +1351,7 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, float diff_mat[4][4]; /* calculate difference matrix if parent object */ - BKE_gpencil_parent_matrix_get(p->depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, obact, gpl, diff_mat); if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) { const float depth_mval = view3d_point_depth(rv3d, mval_3d); @@ -1731,7 +1733,7 @@ static void gpencil_stroke_doeraser(tGPsdata *p) continue; } /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); /* loop over strokes, checking segments for intersections */ LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { @@ -2103,6 +2105,11 @@ static void gpencil_paint_initstroke(tGPsdata *p, copy_v3_v3(p->gpl->color, p->custom_color); } } + + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(p->gpl->layer_mat, p->gpl->location, p->gpl->rotation, p->gpl->scale); + invert_m4_m4(p->gpl->layer_invmat, p->gpl->layer_mat); + if ((paintmode != GP_PAINTMODE_ERASER) && (p->gpl->flag & GP_LAYER_LOCKED)) { p->status = GP_STATUS_ERROR; if (G.debug & G_DEBUG) { diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index b457cd819d2..99242e48cc1 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -317,6 +317,10 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) } tgpi->gpl = gpl; + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* create a new temporary frame */ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe"); tgpi->gpf->framenum = tgpi->cframe = cfra; @@ -1004,12 +1008,12 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* reproject current */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x); tpt->uv_fac = tgpi->totpixlen; } @@ -1067,7 +1071,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) float origin[3]; ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1); + tgpi->scene, tgpi->ob, tgpi->rv3d, tgpi->gpl, gps, origin, ts->gp_sculpt.lock_axis - 1); } /* if parented change position relative to parent object */ diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index bb9dd8cac5d..10b24f4b29f 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1441,11 +1441,6 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, bool changed = false; float rot_eval = 0.0f; - /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { - return false; - } - if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; @@ -1577,6 +1572,13 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, Object *ob = gso->object; bGPdata *gpd = ob->data; char tool = gso->brush->gpencil_sculpt_tool; + GP_SpaceConversion *gsc = &gso->gsc; + Brush *brush = gso->brush; + const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure : + gso->brush->size; + /* Calc bound box matrix. */ + float bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -1588,6 +1590,11 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, continue; } + /* Check if the stroke collide with brush. */ + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { + continue; + } + switch (tool) { case GPSCULPT_TOOL_SMOOTH: /* Smooth strokes */ { @@ -1742,7 +1749,8 @@ static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData * /* calculate difference matrix */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 7c796f7b7a1..b50450eeff3 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -674,7 +674,7 @@ void gpencil_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, b float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); for (i = 0; i < gps->totpoints; i++) { @@ -697,10 +697,11 @@ void gpencil_apply_parent_point(Depsgraph *depsgraph, float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); + copy_v3_v3(&pt->x, fpt); } @@ -997,6 +998,12 @@ void ED_gpencil_drawing_reference_get(const Scene *scene, else { /* use object location */ copy_v3_v3(r_vec, ob->obmat[3]); + /* Apply layer offset. */ + bGPdata *gpd = ob->data; + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + add_v3_v3(r_vec, gpl->layer_mat[3]); + } } } } @@ -1021,7 +1028,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * /* init space conversion stuff */ gpencil_point_conversion_init(C, &gsc); - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); /* Adjust each point */ @@ -1046,6 +1053,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * void ED_gpencil_project_stroke_to_plane(const Scene *scene, const Object *ob, const RegionView3D *rv3d, + bGPDlayer *gpl, bGPDstroke *gps, const float origin[3], const int axis) @@ -1058,6 +1066,10 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, float ray[3]; float rpoint[3]; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* normal vector for a plane locked to axis */ zero_v3(plane_normal); if (axis < 0) { @@ -1074,24 +1086,27 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, copy_m4_m4(mat, ob->obmat); /* move origin to cursor */ + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { copy_v3_v3(mat[3], cursor->location); } mul_mat3_m4_v3(mat, plane_normal); } + + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } else { const float scale[3] = {1.0f, 1.0f, 1.0f}; plane_normal[2] = 1.0f; float mat[4][4]; loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale); - - /* move origin to object */ - if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); - } - mul_mat3_m4_v3(mat, plane_normal); } @@ -1127,8 +1142,12 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, ARegion *region = gsc->region; RegionView3D *rv3d = region->regiondata; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + float diff_mat[4][4], inverse_diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); float origin[3]; @@ -1194,7 +1213,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } } - ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2); + ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2); copy_v3_v3(&pt->x, &pt2.x); @@ -1250,6 +1269,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, */ void ED_gpencil_project_point_to_plane(const Scene *scene, const Object *ob, + bGPDlayer *gpl, const RegionView3D *rv3d, const float origin[3], const int axis, @@ -1277,6 +1297,11 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, if (ob && (ob->type == OB_GPENCIL)) { float mat[4][4]; copy_m4_m4(mat, ob->obmat); + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } /* move origin to cursor */ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { @@ -1284,6 +1309,10 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, } mul_mat3_m4_v3(mat, plane_normal); + /* Apply layer rotation (local transform). */ + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } } else { @@ -1449,7 +1478,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata /* only redo if any change */ if (!equals_m4m4(gpl->inverse, cur_mat)) { /* first apply current transformation to all strokes */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo local object */ sub_v3_v3(diff_mat[3], gpl_loc); @@ -3126,7 +3155,7 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, /* calculate difference matrix object */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); /* Calculate the extremes of the stroke in 2D. */ bGPDspoint pt_parent; diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index 62ddfaab012..c6fa1a0e676 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -825,7 +825,8 @@ static void gpencil_save_selected_point(tGP_BrushVertexpaintData *gso, static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bGPDstroke *gps, const char tool, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -846,7 +847,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bool saved = false; /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return false; } @@ -991,7 +992,8 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, tGP_BrushVertexpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : @@ -1018,7 +1020,7 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, } /* Check points below the brush. */ - bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat); + bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat, bound_mat); /* If stroke was hit and has an editcurve the curve needs an update. */ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; @@ -1123,9 +1125,11 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -1152,7 +1156,7 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert } /* affect strokes in this frame */ - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -1160,7 +1164,8 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert /* Apply to active frame's strokes */ if (gpl->actframe != NULL) { gso->mf_falloff = 1.0f; - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 7fa71fcce3c..3c76478874a 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -383,7 +383,8 @@ static void gpencil_save_selected_point(tGP_BrushWeightpaintData *gso, /* Select points in this stroke and add to an array to be used later. */ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bGPDstroke *gps, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -402,7 +403,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bool include_last = false; /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return; } @@ -505,7 +506,8 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, tGP_BrushWeightpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); char tool = gso->brush->gpencil_weight_tool; @@ -531,7 +533,7 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, } /* Check points below the brush. */ - gpencil_weightpaint_select_stroke(gso, gps, diff_mat); + gpencil_weightpaint_select_stroke(gso, gps, diff_mat, bound_mat); } /*--------------------------------------------------------------------- @@ -578,9 +580,11 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -608,7 +612,7 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig } /* affect strokes in this frame */ - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -616,7 +620,8 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig if (gpl->actframe != NULL) { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 19cec4c0f62..246f6b44fa5 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -263,11 +263,13 @@ bool ED_object_gpencil_exit(struct Main *bmain, struct Object *ob); void ED_gpencil_project_stroke_to_plane(const struct Scene *scene, const struct Object *ob, const struct RegionView3D *rv3d, + struct bGPDlayer *gpl, struct bGPDstroke *gps, const float origin[3], const int axis); void ED_gpencil_project_point_to_plane(const struct Scene *scene, const struct Object *ob, + struct bGPDlayer *gpl, const struct RegionView3D *rv3d, const float origin[3], const int axis, diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 0528d64dca9..13c0740bce6 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1394,7 +1394,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) * (all layers are considered without evaluating lock attributes) */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo matrix */ invert_m4_m4(inverse_diff_mat, diff_mat); LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index 0a742ec4470..6f0269c07a7 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -242,7 +242,7 @@ static void createTransGPencil_curves(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); copy_m3_m4(mtx, diff_mat); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); @@ -507,7 +507,7 @@ static void createTransGPencil_strokes(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* Undo matrix. */ invert_m4_m4(inverse_diff_mat, diff_mat); diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 3c82365fdb4..7eaed2e1924 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -704,7 +704,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { /* skip strokes that are invalid for current view */ diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index e1786304fbb..1dbfd547673 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -512,6 +512,11 @@ typedef struct bGPDlayer { int act_mask; char _pad2[4]; + /** Layer transforms. */ + float location[3], rotation[3], scale[3]; + float layer_mat[4][4], layer_invmat[4][4]; + char _pad3[4]; + bGPDlayer_Runtime runtime; } bGPDlayer; diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 81e20003d8f..dec25c0143f 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -182,6 +182,16 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } +static void rna_GpencilLayerMatrix_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bGPDlayer *gpl = (bGPDlayer *)ptr->data; + + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + + rna_GPencil_update(bmain, scene, ptr); +} + static void rna_GPencil_curve_edit_mode_toggle(Main *bmain, Scene *scene, PointerRNA *ptr) { ToolSettings *ts = scene->toolsettings; @@ -2012,6 +2022,45 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Blend Mode", "Blend mode"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + /* Layer transforms. */ + prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "location"); + RNA_def_property_ui_text(prop, "Location", "Values for change location"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "rotation"); + RNA_def_property_ui_text(prop, "Rotation", "Values for changes in rotation"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Scale", "Values for changes in scale"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + /* Layer matrix. */ + prop = RNA_def_property(srna, "matrix_layer", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "layer_mat"); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Matrix Layer", "Local Layer transformation matrix"); + + /* Layer inverse matrix. */ + prop = RNA_def_property(srna, "matrix_inverse_layer", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "layer_invmat"); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text( + prop, "Matrix Layer Inverse", "Local Layer transformation inverse matrix"); + /* Flags */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE); |