Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/gpencil.c
| Show First 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | static void greasepencil_copy_data(Main *UNUSED(bmain), | ||||
| } | } | ||||
| /* copy layers */ | /* copy layers */ | ||||
| BLI_listbase_clear(&gpd_dst->layers); | BLI_listbase_clear(&gpd_dst->layers); | ||||
| LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { | LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { | ||||
| /* make a copy of source layer and its data */ | /* make a copy of source layer and its data */ | ||||
| /* TODO here too could add unused flags... */ | /* TODO here too could add unused flags... */ | ||||
| bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); | bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src, true, true); | ||||
| /* 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); | BLI_addtail(&gpd_dst->layers, gpl_dst); | ||||
| } | } | ||||
| } | } | ||||
| static void greasepencil_free_data(ID *id) | static void greasepencil_free_data(ID *id) | ||||
| { | { | ||||
| /* Really not ideal, but for now will do... In theory custom behaviors like not freeing cache | /* Really not ideal, but for now will do... In theory custom behaviors like not freeing cache | ||||
| ▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | IDTypeInfo IDType_ID_GD = { | ||||
| .foreach_cache = NULL, | .foreach_cache = NULL, | ||||
| .blend_write = greasepencil_blend_write, | .blend_write = greasepencil_blend_write, | ||||
| .blend_read_data = greasepencil_blend_read_data, | .blend_read_data = greasepencil_blend_read_data, | ||||
| .blend_read_lib = greasepencil_blend_read_lib, | .blend_read_lib = greasepencil_blend_read_lib, | ||||
| .blend_read_expand = greasepencil_blend_read_expand, | .blend_read_expand = greasepencil_blend_read_expand, | ||||
| .blend_read_undo_preserve = NULL, | .blend_read_undo_preserve = NULL, | ||||
| .lib_override_apply_post = NULL, | |||||
| }; | }; | ||||
| /* ************************************************** */ | /* ************************************************** */ | ||||
| /* Draw Engine */ | /* Draw Engine */ | ||||
| void (*BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd) = NULL; | void (*BKE_gpencil_batch_cache_dirty_tag_cb)(bGPdata *gpd) = NULL; | ||||
| void (*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL; | void (*BKE_gpencil_batch_cache_free_cb)(bGPdata *gpd) = NULL; | ||||
| ▲ Show 20 Lines • Show All 262 Lines • ▼ Show 20 Lines | if (gpl == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (gpl->actframe == NULL) { | if (gpl->actframe == NULL) { | ||||
| /* no active frame, so just create a new one from scratch */ | /* no active frame, so just create a new one from scratch */ | ||||
| return BKE_gpencil_frame_addnew(gpl, cframe); | return BKE_gpencil_frame_addnew(gpl, cframe); | ||||
| } | } | ||||
| /* Create a copy of the frame */ | /* Create a copy of the frame */ | ||||
| new_frame = BKE_gpencil_frame_duplicate(gpl->actframe); | new_frame = BKE_gpencil_frame_duplicate(gpl->actframe, true); | ||||
| /* Find frame to insert it before */ | /* Find frame to insert it before */ | ||||
| LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { | LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { | ||||
| if (gpf->framenum > cframe) { | if (gpf->framenum > cframe) { | ||||
| /* Add it here */ | /* Add it here */ | ||||
| BLI_insertlinkbefore(&gpl->frames, gpf, new_frame); | BLI_insertlinkbefore(&gpl->frames, gpf, new_frame); | ||||
| found = true; | found = true; | ||||
| ▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | BLI_uniquename(&gpd->layers, | ||||
| gpl, | gpl, | ||||
| (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"), | (gpd->flag & GP_DATA_ANNOTATIONS) ? DATA_("Note") : DATA_("GP_Layer"), | ||||
| '.', | '.', | ||||
| offsetof(bGPDlayer, info), | offsetof(bGPDlayer, info), | ||||
| sizeof(gpl->info)); | sizeof(gpl->info)); | ||||
| /* Enable always affected by scene lights. */ | /* Enable always affected by scene lights. */ | ||||
| gpl->flag |= GP_LAYER_USE_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 */ | /* make this one the active one */ | ||||
| if (setactive) { | if (setactive) { | ||||
| BKE_gpencil_layer_active_set(gpd, gpl); | BKE_gpencil_layer_active_set(gpd, gpl); | ||||
| } | } | ||||
| /* return layer */ | /* return layer */ | ||||
| return gpl; | return gpl; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, | ||||
| return gps_dst; | return gps_dst; | ||||
| } | } | ||||
| /** | /** | ||||
| * Make a copy of a given gpencil frame. | * Make a copy of a given gpencil frame. | ||||
| * \param gpf_src: Source grease pencil frame | * \param gpf_src: Source grease pencil frame | ||||
| * \return Pointer to new frame | * \return Pointer to new frame | ||||
| */ | */ | ||||
| bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src) | bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes) | ||||
| { | { | ||||
| bGPDstroke *gps_dst = NULL; | bGPDstroke *gps_dst = NULL; | ||||
| bGPDframe *gpf_dst; | bGPDframe *gpf_dst; | ||||
| /* error checking */ | /* error checking */ | ||||
| if (gpf_src == NULL) { | if (gpf_src == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* make a copy of the source frame */ | /* make a copy of the source frame */ | ||||
| gpf_dst = MEM_dupallocN(gpf_src); | gpf_dst = MEM_dupallocN(gpf_src); | ||||
| gpf_dst->prev = gpf_dst->next = NULL; | gpf_dst->prev = gpf_dst->next = NULL; | ||||
| /* copy strokes */ | /* Copy strokes. */ | ||||
| BLI_listbase_clear(&gpf_dst->strokes); | BLI_listbase_clear(&gpf_dst->strokes); | ||||
| if (dup_strokes) { | |||||
| LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { | LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { | ||||
| /* make copy of source stroke */ | /* make copy of source stroke */ | ||||
| gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true); | gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true); | ||||
| BLI_addtail(&gpf_dst->strokes, gps_dst); | BLI_addtail(&gpf_dst->strokes, gps_dst); | ||||
| } | } | ||||
| } | |||||
| /* return new frame */ | /* return new frame */ | ||||
| return gpf_dst; | return gpf_dst; | ||||
| } | } | ||||
| /** | /** | ||||
| * Make a copy of strokes between gpencil frames. | * Make a copy of strokes between gpencil frames. | ||||
| * \param gpf_src: Source grease pencil frame | * \param gpf_src: Source grease pencil frame | ||||
| Show All 16 Lines | void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_dst) | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Make a copy of a given gpencil layer. | * Make a copy of a given gpencil layer. | ||||
| * \param gpl_src: Source grease pencil layer | * \param gpl_src: Source grease pencil layer | ||||
| * \return Pointer to new layer | * \return Pointer to new layer | ||||
| */ | */ | ||||
| bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src) | bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, | ||||
| const bool dup_frames, | |||||
| const bool dup_strokes) | |||||
| { | { | ||||
| const bGPDframe *gpf_src; | const bGPDframe *gpf_src; | ||||
| bGPDframe *gpf_dst; | bGPDframe *gpf_dst; | ||||
| bGPDlayer *gpl_dst; | bGPDlayer *gpl_dst; | ||||
| /* error checking */ | /* error checking */ | ||||
| if (gpl_src == NULL) { | if (gpl_src == NULL) { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* make a copy of source layer */ | /* make a copy of source layer */ | ||||
| gpl_dst = MEM_dupallocN(gpl_src); | gpl_dst = MEM_dupallocN(gpl_src); | ||||
| gpl_dst->prev = gpl_dst->next = NULL; | gpl_dst->prev = gpl_dst->next = NULL; | ||||
| /* Copy masks. */ | /* Copy masks. */ | ||||
| BLI_listbase_clear(&gpl_dst->mask_layers); | BLI_listbase_clear(&gpl_dst->mask_layers); | ||||
| LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) { | LISTBASE_FOREACH (bGPDlayer_Mask *, mask_src, &gpl_src->mask_layers) { | ||||
| bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src); | bGPDlayer_Mask *mask_dst = MEM_dupallocN(mask_src); | ||||
| mask_dst->prev = mask_dst->next = NULL; | mask_dst->prev = mask_dst->next = NULL; | ||||
| BLI_addtail(&gpl_dst->mask_layers, mask_dst); | BLI_addtail(&gpl_dst->mask_layers, mask_dst); | ||||
| } | } | ||||
| /* copy frames */ | /* copy frames */ | ||||
| BLI_listbase_clear(&gpl_dst->frames); | BLI_listbase_clear(&gpl_dst->frames); | ||||
| if (dup_frames) { | |||||
| for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) { | for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) { | ||||
| /* make a copy of source frame */ | /* make a copy of source frame */ | ||||
| gpf_dst = BKE_gpencil_frame_duplicate(gpf_src); | gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, dup_strokes); | ||||
| BLI_addtail(&gpl_dst->frames, gpf_dst); | BLI_addtail(&gpl_dst->frames, gpf_dst); | ||||
| /* if source frame was the current layer's 'active' frame, reassign that too */ | /* if source frame was the current layer's 'active' frame, reassign that too */ | ||||
| if (gpf_src == gpl_dst->actframe) { | if (gpf_src == gpl_dst->actframe) { | ||||
| gpl_dst->actframe = gpf_dst; | gpl_dst->actframe = gpf_dst; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| /* return new layer */ | /* return new layer */ | ||||
| return gpl_dst; | return gpl_dst; | ||||
| } | } | ||||
| /** | /** | ||||
| * Make a copy of a given gpencil data-block. | * Make a copy of a given gpencil data-block. | ||||
| * | * | ||||
| ▲ Show 20 Lines • Show All 1,458 Lines • ▼ Show 20 Lines | void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, | ||||
| Object *ob, | Object *ob, | ||||
| gpIterCb layer_cb, | gpIterCb layer_cb, | ||||
| gpIterCb stroke_cb, | gpIterCb stroke_cb, | ||||
| void *thunk, | void *thunk, | ||||
| bool do_onion, | bool do_onion, | ||||
| int cfra) | int cfra) | ||||
| { | { | ||||
| bGPdata *gpd = (bGPdata *)ob->data; | bGPdata *gpd = (bGPdata *)ob->data; | ||||
| const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); | const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd))); | ||||
| const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0); | const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0); | ||||
| const bool is_drawing = (gpd->runtime.sbuffer_used > 0); | const bool is_drawing = (gpd->runtime.sbuffer_used > 0); | ||||
| /* Onion skinning. */ | /* Onion skinning. */ | ||||
| const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE); | const bool onion_mode_abs = (gpd->onion_mode == GP_ONION_MODE_ABSOLUTE); | ||||
| const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED); | const bool onion_mode_sel = (gpd->onion_mode == GP_ONION_MODE_SELECTED); | ||||
| const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0; | const bool onion_loop = (gpd->onion_flag & GP_ONION_LOOP) != 0; | ||||
| const short onion_keytype = gpd->onion_keytype; | const short onion_keytype = gpd->onion_keytype; | ||||
| LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { | LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { | ||||
| /* Reset by layer. */ | /* Reset by layer. */ | ||||
| bool is_before_first = false; | bool is_before_first = false; | ||||
| bGPDframe *act_gpf = gpl->actframe; | bGPDframe *act_gpf = gpl->actframe; | ||||
| bGPDframe *sta_gpf = act_gpf; | bGPDframe *sta_gpf = act_gpf; | ||||
| bGPDframe *end_gpf = act_gpf ? act_gpf->next : NULL; | bGPDframe *end_gpf = act_gpf ? act_gpf->next : NULL; | ||||
| if (gpl->flag & GP_LAYER_HIDE) { | if (gpl->flag & GP_LAYER_HIDE) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* If scale to 0 the layer must be invisible. */ | |||||
| if (is_zero_v3(gpl->scale)) { | |||||
| continue; | |||||
| } | |||||
| /* Hide the layer if it's defined a view layer filter. This is used to | /* Hide the layer if it's defined a view layer filter. This is used to | ||||
| * generate renders, putting only selected GP layers for each View Layer. | * generate renders, putting only selected GP layers for each View Layer. | ||||
| * This is used only in final render and never in Viewport. */ | * This is used only in final render and never in Viewport. */ | ||||
| if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') && | if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') && | ||||
| (!STREQ(view_layer->name, gpl->viewlayername))) { | (!STREQ(view_layer->name, gpl->viewlayername))) { | ||||
| /* If the layer is used as mask, cannot be filtered or the masking system | /* If the layer is used as mask, cannot be filtered or the masking system | ||||
| * will crash because needs the mask layer in the draw pipeline. */ | * will crash because needs the mask layer in the draw pipeline. */ | ||||
| if (!gpencil_is_layer_mask(view_layer, gpd, gpl)) { | if (!gpencil_is_layer_mask(view_layer, gpd, gpl)) { | ||||
| ▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | |||||
| /** | /** | ||||
| * Get parent matrix, including layer parenting. | * Get parent matrix, including layer parenting. | ||||
| * \param depsgraph: Depsgraph | * \param depsgraph: Depsgraph | ||||
| * \param obact: Grease pencil object | * \param obact: Grease pencil object | ||||
| * \param gpl: Grease pencil layer | * \param gpl: Grease pencil layer | ||||
| * \param diff_mat: Result parent matrix | * \param diff_mat: Result parent matrix | ||||
| */ | */ | ||||
| void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, | void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, | ||||
| Object *obact, | Object *obact, | ||||
| bGPDlayer *gpl, | bGPDlayer *gpl, | ||||
| float diff_mat[4][4]) | float diff_mat[4][4]) | ||||
| { | { | ||||
| Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; | Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; | ||||
| Object *obparent = gpl->parent; | Object *obparent = gpl->parent; | ||||
| Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) : | Object *obparent_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obparent) : | ||||
| obparent; | obparent; | ||||
| /* if not layer parented, try with object parented */ | /* if not layer parented, try with object parented */ | ||||
| if (obparent_eval == NULL) { | if (obparent_eval == NULL) { | ||||
| if (ob_eval != NULL) { | if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) { | ||||
| if (ob_eval->type == OB_GPENCIL) { | |||||
| copy_m4_m4(diff_mat, ob_eval->obmat); | copy_m4_m4(diff_mat, ob_eval->obmat); | ||||
| mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); | |||||
| return; | return; | ||||
| } | } | ||||
| } | |||||
| /* not gpencil object */ | /* not gpencil object */ | ||||
| unit_m4(diff_mat); | unit_m4(diff_mat); | ||||
| return; | return; | ||||
| } | } | ||||
| if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { | if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { | ||||
| mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); | mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); | ||||
| add_v3_v3(diff_mat[3], ob_eval->obmat[3]); | add_v3_v3(diff_mat[3], ob_eval->obmat[3]); | ||||
| mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); | |||||
| return; | return; | ||||
| } | } | ||||
| if (gpl->partype == PARBONE) { | if (gpl->partype == PARBONE) { | ||||
| bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr); | bPoseChannel *pchan = BKE_pose_channel_find_name(obparent_eval->pose, gpl->parsubstr); | ||||
| if (pchan) { | if (pchan) { | ||||
| float tmp_mat[4][4]; | float tmp_mat[4][4]; | ||||
| mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat); | mul_m4_m4m4(tmp_mat, obparent_eval->obmat, pchan->pose_mat); | ||||
| mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse); | mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse); | ||||
| add_v3_v3(diff_mat[3], ob_eval->obmat[3]); | add_v3_v3(diff_mat[3], ob_eval->obmat[3]); | ||||
| } | } | ||||
| else { | else { | ||||
| /* if bone not found use object (armature) */ | /* if bone not found use object (armature) */ | ||||
| mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); | mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); | ||||
| add_v3_v3(diff_mat[3], ob_eval->obmat[3]); | add_v3_v3(diff_mat[3], ob_eval->obmat[3]); | ||||
| } | } | ||||
| mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); | |||||
| return; | return; | ||||
| } | } | ||||
| unit_m4(diff_mat); /* not defined type */ | unit_m4(diff_mat); /* not defined type */ | ||||
| } | } | ||||
| /** | /** | ||||
| * Update parent matrix. | * Update parent matrix and local transforms. | ||||
| * \param depsgraph: Depsgraph | * \param depsgraph: Depsgraph | ||||
| * \param ob: Grease pencil object | * \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) { | if (ob->type != OB_GPENCIL) { | ||||
| return; | return; | ||||
| } | } | ||||
| bGPdata *gpd = (bGPdata *)ob->data; | bGPdata *gpd = (bGPdata *)ob->data; | ||||
| float cur_mat[4][4]; | float cur_mat[4][4]; | ||||
| bool changed = false; | |||||
| LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { | LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { | ||||
| if ((gpl->parent != NULL) && (gpl->actframe != NULL)) { | unit_m4(cur_mat); | ||||
| if (gpl->actframe != NULL) { | |||||
| if (gpl->parent != NULL) { | |||||
| Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); | Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); | ||||
| /* calculate new matrix */ | /* calculate new matrix */ | ||||
| if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { | if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { | ||||
| copy_m4_m4(cur_mat, ob_parent->obmat); | copy_m4_m4(cur_mat, ob_parent->obmat); | ||||
| } | } | ||||
| else if (gpl->partype == PARBONE) { | else if (gpl->partype == PARBONE) { | ||||
| bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); | bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); | ||||
| if (pchan != NULL) { | if (pchan != NULL) { | ||||
| copy_m4_m4(cur_mat, ob->imat); | copy_m4_m4(cur_mat, ob->imat); | ||||
| mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); | mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); | ||||
| } | } | ||||
| else { | else { | ||||
| unit_m4(cur_mat); | 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 */ | /* only redo if any change */ | ||||
| if (!equals_m4m4(gpl->inverse, cur_mat)) { | if (changed || transfomed) { | ||||
| LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { | LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { | ||||
| bGPDspoint *pt; | bGPDspoint *pt; | ||||
| int i; | int i; | ||||
| for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { | for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { | ||||
| if (changed) { | |||||
| mul_m4_v3(gpl->inverse, &pt->x); | mul_m4_v3(gpl->inverse, &pt->x); | ||||
| mul_m4_v3(cur_mat, &pt->x); | mul_m4_v3(cur_mat, &pt->x); | ||||
| } | } | ||||
| if (transfomed) { | |||||
| mul_m4_v3(gpl->layer_mat, &pt->x); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Find material by name prefix. | * Find material by name prefix. | ||||
| Show All 19 Lines | |||||