From b31f5b8ce7ae0f3f8195dc04a2006945fe6b4bff Mon Sep 17 00:00:00 2001 From: Yann Lanthony Date: Wed, 4 May 2022 12:54:09 +0200 Subject: GPencil: Apply layer transforms to visible frames Fix regression described in T97799. Apply layer transform and layer parenting to all visible frames, i.e. active frame + onion skinning frames. Reviewed By: #grease_pencil, antoniov Maniphest Tasks: T97799 Differential Revision: https://developer.blender.org/D14829 --- source/blender/blenkernel/intern/gpencil.c | 84 ++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 087d8b8fcd4..84621be1960 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -2742,35 +2742,75 @@ void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob) LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bool changed = false; 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)) { - mul_m4_m4m4(cur_mat, ob->imat, ob_parent->obmat); + + /* Skip non-visible layers. */ + if (gpl->flag & GP_LAYER_HIDE || is_zero_v3(gpl->scale)) { + continue; + } + + /* Skip empty layers. */ + if (BLI_listbase_is_empty(&gpl->frames)) { + continue; + } + + /* Determine frame range to transform. */ + bGPDframe *gpf_start = NULL; + bGPDframe *gpf_end = NULL; + + /* If onion skinning is activated, consider all frames. */ + if (gpl->onion_flag & GP_LAYER_ONIONSKIN) { + gpf_start = gpl->frames.first; + } + /* Otherwise, consider only active frame. */ + else { + /* Skip layer if it has no active frame to transform. */ + if (gpl->actframe == NULL) { + continue; + } + gpf_start = gpl->actframe; + gpf_end = gpl->actframe->next; + } + + if (gpl->parent != NULL) { + Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); + /* calculate new matrix */ + if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { + mul_m4_m4m4(cur_mat, ob->imat, ob_parent->obmat); + } + else if (gpl->partype == PARBONE) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); + if (pchan != NULL) { + mul_m4_series(cur_mat, ob->imat, ob_parent->obmat, pchan->pose_mat); } - else if (gpl->partype == PARBONE) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); - if (pchan != NULL) { - mul_m4_series(cur_mat, ob->imat, ob_parent->obmat, pchan->pose_mat); - } - else { - unit_m4(cur_mat); - } + else { + unit_m4(cur_mat); } - changed = !equals_m4m4(gpl->inverse, cur_mat); } + changed = !equals_m4m4(gpl->inverse, cur_mat); + } - /* Calc local layer transform. */ - bool transformed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || - (!is_one_v3(gpl->scale))); - if (transformed) { - loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + /* Calc local layer transform. */ + bool transformed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || + (!is_one_v3(gpl->scale))); + if (transformed) { + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + } + + /* Continue if no transformations are applied to this layer. */ + if (!changed && !transformed) { + continue; + } + + /* Iterate over frame range. */ + for (bGPDframe *gpf = gpf_start; gpf != NULL && gpf != gpf_end; gpf = gpf->next) { + /* Skip frames without a valid onion skinning id (note: active frame has one). */ + if (gpf->runtime.onion_id == INT_MAX) { + continue; } - /* only redo if any change */ + /* Apply transformations only if needed. */ if (changed || transformed) { - LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; int i; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { -- cgit v1.2.3