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
This commit is contained in:
Yann Lanthony 2022-05-04 12:54:09 +02:00 committed by Falk David
parent 302584bd6e
commit b31f5b8ce7
Notes: blender-bot 2023-05-03 10:14:48 +02:00
Referenced by issue #97799, Regression: Transforming a layer in GreasePencil doesn't transform Onion skin in >3.2
1 changed files with 64 additions and 24 deletions

View File

@ -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);
}
/* 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;
}
/* 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);
}
/* 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++) {