diff options
Diffstat (limited to 'source/blender/editors/gpencil/editaction_gpencil.c')
-rw-r--r-- | source/blender/editors/gpencil/editaction_gpencil.c | 852 |
1 files changed, 424 insertions, 428 deletions
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 8ada5a05618..4724dc068b6 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -21,7 +21,6 @@ * \ingroup edgpencil */ - #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -59,21 +58,21 @@ /* Loops over the gp-frames for a gp-layer, and applies the given callback */ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPDframe *, Scene *)) { - bGPDframe *gpf; + bGPDframe *gpf; - /* error checker */ - if (gpl == NULL) - return false; + /* error checker */ + if (gpl == NULL) + return false; - /* do loop */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - /* execute callback */ - if (gpf_cb(gpf, scene)) - return true; - } + /* do loop */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + /* execute callback */ + if (gpf_cb(gpf, scene)) + return true; + } - /* nothing to return */ - return false; + /* nothing to return */ + return false; } /* ****************************************** */ @@ -82,24 +81,24 @@ bool ED_gplayer_frames_looper(bGPDlayer *gpl, Scene *scene, short (*gpf_cb)(bGPD /* make a listing all the gp-frames in a layer as cfraelems */ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) { - bGPDframe *gpf; - CfraElem *ce; + bGPDframe *gpf; + CfraElem *ce; - /* error checking */ - if (ELEM(NULL, gpl, elems)) - return; + /* error checking */ + if (ELEM(NULL, gpl, elems)) + return; - /* loop through gp-frames, adding */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) { - ce = MEM_callocN(sizeof(CfraElem), "CfraElem"); + /* loop through gp-frames, adding */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if ((onlysel == 0) || (gpf->flag & GP_FRAME_SELECT)) { + ce = MEM_callocN(sizeof(CfraElem), "CfraElem"); - ce->cfra = (float)gpf->framenum; - ce->sel = (gpf->flag & GP_FRAME_SELECT) ? 1 : 0; + ce->cfra = (float)gpf->framenum; + ce->sel = (gpf->flag & GP_FRAME_SELECT) ? 1 : 0; - BLI_addtail(elems, ce); - } - } + BLI_addtail(elems, ce); + } + } } /* ***************************************** */ @@ -108,125 +107,128 @@ void ED_gplayer_make_cfra_list(bGPDlayer *gpl, ListBase *elems, bool onlysel) /* check if one of the frames in this layer is selected */ bool ED_gplayer_frame_select_check(bGPDlayer *gpl) { - bGPDframe *gpf; + bGPDframe *gpf; - /* error checking */ - if (gpl == NULL) - return false; + /* error checking */ + if (gpl == NULL) + return false; - /* stop at the first one found */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (gpf->flag & GP_FRAME_SELECT) - return true; - } + /* stop at the first one found */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if (gpf->flag & GP_FRAME_SELECT) + return true; + } - /* not found */ - return false; + /* not found */ + return false; } /* helper function - select gp-frame based on SELECT_* mode */ static void gpframe_select(bGPDframe *gpf, short select_mode) { - if (gpf == NULL) - return; - - switch (select_mode) { - case SELECT_ADD: - gpf->flag |= GP_FRAME_SELECT; - break; - case SELECT_SUBTRACT: - gpf->flag &= ~GP_FRAME_SELECT; - break; - case SELECT_INVERT: - gpf->flag ^= GP_FRAME_SELECT; - break; - } + if (gpf == NULL) + return; + + switch (select_mode) { + case SELECT_ADD: + gpf->flag |= GP_FRAME_SELECT; + break; + case SELECT_SUBTRACT: + gpf->flag &= ~GP_FRAME_SELECT; + break; + case SELECT_INVERT: + gpf->flag ^= GP_FRAME_SELECT; + break; + } } /* set all/none/invert select (like above, but with SELECT_* modes) */ void ED_gpencil_select_frames(bGPDlayer *gpl, short select_mode) { - bGPDframe *gpf; + bGPDframe *gpf; - /* error checking */ - if (gpl == NULL) - return; + /* error checking */ + if (gpl == NULL) + return; - /* handle according to mode */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - gpframe_select(gpf, select_mode); - } + /* handle according to mode */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + gpframe_select(gpf, select_mode); + } } /* set all/none/invert select */ void ED_gplayer_frame_select_set(bGPDlayer *gpl, short mode) { - /* error checking */ - if (gpl == NULL) - return; + /* error checking */ + if (gpl == NULL) + return; - /* now call the standard function */ - ED_gpencil_select_frames(gpl, mode); + /* now call the standard function */ + ED_gpencil_select_frames(gpl, mode); } /* select the frame in this layer that occurs on this frame (there should only be one at most) */ void ED_gpencil_select_frame(bGPDlayer *gpl, int selx, short select_mode) { - bGPDframe *gpf; + bGPDframe *gpf; - if (gpl == NULL) - return; + if (gpl == NULL) + return; - gpf = BKE_gpencil_layer_find_frame(gpl, selx); + gpf = BKE_gpencil_layer_find_frame(gpl, selx); - if (gpf) { - gpframe_select(gpf, select_mode); - } + if (gpf) { + gpframe_select(gpf, select_mode); + } } /* select the frames in this layer that occur within the bounds specified */ void ED_gplayer_frames_select_box(bGPDlayer *gpl, float min, float max, short select_mode) { - bGPDframe *gpf; + bGPDframe *gpf; - if (gpl == NULL) - return; + if (gpl == NULL) + return; - /* only select those frames which are in bounds */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (IN_RANGE(gpf->framenum, min, max)) - gpframe_select(gpf, select_mode); - } + /* only select those frames which are in bounds */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if (IN_RANGE(gpf->framenum, min, max)) + gpframe_select(gpf, select_mode); + } } /* select the frames in this layer that occur within the lasso/circle region specified */ -void ED_gplayer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, short tool, short select_mode) +void ED_gplayer_frames_select_region(KeyframeEditData *ked, + bGPDlayer *gpl, + short tool, + short select_mode) { - bGPDframe *gpf; - - if (gpl == NULL) - return; - - /* only select frames which are within the region */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - /* construct a dummy point coordinate to do this testing with */ - float pt[2] = {0}; - - pt[0] = gpf->framenum; - pt[1] = ked->channel_y; - - /* check the necessary regions */ - if (tool == BEZT_OK_CHANNEL_LASSO) { - /* Lasso */ - if (keyframe_region_lasso_test(ked->data, pt)) - gpframe_select(gpf, select_mode); - } - else if (tool == BEZT_OK_CHANNEL_CIRCLE) { - /* Circle */ - if (keyframe_region_circle_test(ked->data, pt)) - gpframe_select(gpf, select_mode); - } - } + bGPDframe *gpf; + + if (gpl == NULL) + return; + + /* only select frames which are within the region */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + /* construct a dummy point coordinate to do this testing with */ + float pt[2] = {0}; + + pt[0] = gpf->framenum; + pt[1] = ked->channel_y; + + /* check the necessary regions */ + if (tool == BEZT_OK_CHANNEL_LASSO) { + /* Lasso */ + if (keyframe_region_lasso_test(ked->data, pt)) + gpframe_select(gpf, select_mode); + } + else if (tool == BEZT_OK_CHANNEL_CIRCLE) { + /* Circle */ + if (keyframe_region_circle_test(ked->data, pt)) + gpframe_select(gpf, select_mode); + } + } } /* ***************************************** */ @@ -235,50 +237,50 @@ void ED_gplayer_frames_select_region(KeyframeEditData *ked, bGPDlayer *gpl, shor /* Delete selected frames */ bool ED_gplayer_frames_delete(bGPDlayer *gpl) { - bGPDframe *gpf, *gpfn; - bool changed = false; + bGPDframe *gpf, *gpfn; + bool changed = false; - /* error checking */ - if (gpl == NULL) - return false; + /* error checking */ + if (gpl == NULL) + return false; - /* check for frames to delete */ - for (gpf = gpl->frames.first; gpf; gpf = gpfn) { - gpfn = gpf->next; + /* check for frames to delete */ + for (gpf = gpl->frames.first; gpf; gpf = gpfn) { + gpfn = gpf->next; - if (gpf->flag & GP_FRAME_SELECT) { - BKE_gpencil_layer_delframe(gpl, gpf); - changed = true; - } - } + if (gpf->flag & GP_FRAME_SELECT) { + BKE_gpencil_layer_delframe(gpl, gpf); + changed = true; + } + } - return changed; + return changed; } /* Duplicate selected frames from given gp-layer */ void ED_gplayer_frames_duplicate(bGPDlayer *gpl) { - bGPDframe *gpf, *gpfn; + bGPDframe *gpf, *gpfn; - /* error checking */ - if (gpl == NULL) - return; + /* error checking */ + if (gpl == NULL) + return; - /* duplicate selected frames */ - for (gpf = gpl->frames.first; gpf; gpf = gpfn) { - gpfn = gpf->next; + /* duplicate selected frames */ + for (gpf = gpl->frames.first; gpf; gpf = gpfn) { + gpfn = gpf->next; - /* duplicate this frame */ - if (gpf->flag & GP_FRAME_SELECT) { - bGPDframe *gpfd; + /* duplicate this frame */ + if (gpf->flag & GP_FRAME_SELECT) { + bGPDframe *gpfd; - /* duplicate frame, and deselect self */ - gpfd = BKE_gpencil_frame_duplicate(gpf); - gpf->flag &= ~GP_FRAME_SELECT; + /* duplicate frame, and deselect self */ + gpfd = BKE_gpencil_frame_duplicate(gpf); + gpf->flag &= ~GP_FRAME_SELECT; - BLI_insertlinkafter(&gpl->frames, gpf, gpfd); - } - } + BLI_insertlinkafter(&gpl->frames, gpf, gpfd); + } + } } /* Set keyframe type for selected frames from given gp-layer @@ -286,19 +288,18 @@ void ED_gplayer_frames_duplicate(bGPDlayer *gpl) */ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type) { - bGPDframe *gpf; + bGPDframe *gpf; - if (gpl == NULL) - return; + if (gpl == NULL) + return; - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - if (gpf->flag & GP_FRAME_SELECT) { - gpf->key_type = type; - } - } + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + if (gpf->flag & GP_FRAME_SELECT) { + gpf->key_type = type; + } + } } - /* -------------------------------------- */ /* Copy and Paste Tools */ /* - The copy/paste buffer currently stores a set of GP_Layers, with temporary @@ -311,23 +312,21 @@ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type) /* globals for copy/paste data (like for other copy/paste buffers) */ static ListBase gp_anim_copybuf = {NULL, NULL}; -static int gp_anim_copy_firstframe = 999999999; -static int gp_anim_copy_lastframe = -999999999; -static int gp_anim_copy_cfra = 0; - +static int gp_anim_copy_firstframe = 999999999; +static int gp_anim_copy_lastframe = -999999999; +static int gp_anim_copy_cfra = 0; /* This function frees any MEM_calloc'ed copy/paste buffer data */ void ED_gpencil_anim_copybuf_free(void) { - BKE_gpencil_free_layers(&gp_anim_copybuf); - BLI_listbase_clear(&gp_anim_copybuf); + BKE_gpencil_free_layers(&gp_anim_copybuf); + BLI_listbase_clear(&gp_anim_copybuf); - gp_anim_copy_firstframe = 999999999; - gp_anim_copy_lastframe = -999999999; - gp_anim_copy_cfra = 0; + gp_anim_copy_firstframe = 999999999; + gp_anim_copy_lastframe = -999999999; + gp_anim_copy_cfra = 0; } - /* This function adds data to the copy/paste buffer, freeing existing data first * Only the selected GP-layers get their selected keyframes copied. * @@ -335,180 +334,177 @@ void ED_gpencil_anim_copybuf_free(void) */ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - Scene *scene = ac->scene; - - - /* clear buffer first */ - ED_gpencil_anim_copybuf_free(); - - /* filter data */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* assume that each of these is a GP layer */ - for (ale = anim_data.first; ale; ale = ale->next) { - ListBase copied_frames = {NULL, NULL}; - bGPDlayer *gpl = (bGPDlayer *)ale->data; - bGPDframe *gpf; - - /* loop over frames, and copy only selected frames */ - for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { - /* if frame is selected, make duplicate it and its strokes */ - if (gpf->flag & GP_FRAME_SELECT) { - /* make a copy of this frame */ - bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf); - BLI_addtail(&copied_frames, new_frame); - - /* extend extents for keyframes encountered */ - if (gpf->framenum < gp_anim_copy_firstframe) - gp_anim_copy_firstframe = gpf->framenum; - if (gpf->framenum > gp_anim_copy_lastframe) - gp_anim_copy_lastframe = gpf->framenum; - } - } - - /* create a new layer in buffer if there were keyframes here */ - if (BLI_listbase_is_empty(&copied_frames) == false) { - bGPDlayer *new_layer = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer"); - BLI_addtail(&gp_anim_copybuf, new_layer); - - /* move over copied frames */ - BLI_movelisttolist(&new_layer->frames, &copied_frames); - BLI_assert(copied_frames.first == NULL); - - /* make a copy of the layer's name - for name-based matching later... */ - BLI_strncpy(new_layer->info, gpl->info, sizeof(new_layer->info)); - } - } - - /* in case 'relative' paste method is used */ - gp_anim_copy_cfra = CFRA; - - /* clean up */ - ANIM_animdata_freelist(&anim_data); - - /* check if anything ended up in the buffer */ - if (ELEM(NULL, gp_anim_copybuf.first, gp_anim_copybuf.last)) { - BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); - return false; - } - - /* report success */ - return true; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene = ac->scene; + + /* clear buffer first */ + ED_gpencil_anim_copybuf_free(); + + /* filter data */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* assume that each of these is a GP layer */ + for (ale = anim_data.first; ale; ale = ale->next) { + ListBase copied_frames = {NULL, NULL}; + bGPDlayer *gpl = (bGPDlayer *)ale->data; + bGPDframe *gpf; + + /* loop over frames, and copy only selected frames */ + for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { + /* if frame is selected, make duplicate it and its strokes */ + if (gpf->flag & GP_FRAME_SELECT) { + /* make a copy of this frame */ + bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf); + BLI_addtail(&copied_frames, new_frame); + + /* extend extents for keyframes encountered */ + if (gpf->framenum < gp_anim_copy_firstframe) + gp_anim_copy_firstframe = gpf->framenum; + if (gpf->framenum > gp_anim_copy_lastframe) + gp_anim_copy_lastframe = gpf->framenum; + } + } + + /* create a new layer in buffer if there were keyframes here */ + if (BLI_listbase_is_empty(&copied_frames) == false) { + bGPDlayer *new_layer = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer"); + BLI_addtail(&gp_anim_copybuf, new_layer); + + /* move over copied frames */ + BLI_movelisttolist(&new_layer->frames, &copied_frames); + BLI_assert(copied_frames.first == NULL); + + /* make a copy of the layer's name - for name-based matching later... */ + BLI_strncpy(new_layer->info, gpl->info, sizeof(new_layer->info)); + } + } + + /* in case 'relative' paste method is used */ + gp_anim_copy_cfra = CFRA; + + /* clean up */ + ANIM_animdata_freelist(&anim_data); + + /* check if anything ended up in the buffer */ + if (ELEM(NULL, gp_anim_copybuf.first, gp_anim_copybuf.last)) { + BKE_report(ac->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); + return false; + } + + /* report success */ + return true; } - /* Pastes keyframes from buffer, and reports success */ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) { - ListBase anim_data = {NULL, NULL}; - bAnimListElem *ale; - int filter; - - Scene *scene = ac->scene; - bool no_name = false; - int offset = 0; - - /* check if buffer is empty */ - if (BLI_listbase_is_empty(&gp_anim_copybuf)) { - BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste"); - return false; - } - - /* check if single channel in buffer (disregard names if so) */ - if (gp_anim_copybuf.first == gp_anim_copybuf.last) { - no_name = true; - } - - /* methods of offset (eKeyPasteOffset) */ - switch (offset_mode) { - case KEYFRAME_PASTE_OFFSET_CFRA_START: - offset = (CFRA - gp_anim_copy_firstframe); - break; - case KEYFRAME_PASTE_OFFSET_CFRA_END: - offset = (CFRA - gp_anim_copy_lastframe); - break; - case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE: - offset = (CFRA - gp_anim_copy_cfra); - break; - case KEYFRAME_PASTE_OFFSET_NONE: - offset = 0; - break; - } - - - /* filter data */ - // TODO: try doing it with selection, then without selection imits - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); - ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - - /* from selected channels */ - for (ale = anim_data.first; ale; ale = ale->next) { - bGPDlayer *gpld = (bGPDlayer *)ale->data; - bGPDlayer *gpls = NULL; - bGPDframe *gpfs, *gpf; - - - /* find suitable layer from buffer to use to paste from */ - for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) { - /* check if layer name matches */ - if ((no_name) || STREQ(gpls->info, gpld->info)) { - break; - } - } - - /* this situation might occur! */ - if (gpls == NULL) - continue; - - /* add frames from buffer */ - for (gpfs = gpls->frames.first; gpfs; gpfs = gpfs->next) { - /* temporarily apply offset to buffer-frame while copying */ - gpfs->framenum += offset; - - /* get frame to copy data into (if no frame returned, then just ignore) */ - gpf = BKE_gpencil_layer_getframe(gpld, gpfs->framenum, GP_GETFRAME_ADD_NEW); - if (gpf) { - bGPDstroke *gps, *gpsn; - - /* This should be the right frame... as it may be a pre-existing frame, - * must make sure that only compatible stroke types get copied over - * - We cannot just add a duplicate frame, as that would cause errors - * - For now, we don't check if the types will be compatible since we - * don't have enough info to do so. Instead, we simply just paste, - * if it works, it will show up. - */ - for (gps = gpfs->strokes.first; gps; gps = gps->next) { - /* make a copy of stroke, then of its points array */ - gpsn = MEM_dupallocN(gps); - gpsn->points = MEM_dupallocN(gps->points); - if (gps->dvert != NULL) { - gpsn->dvert = MEM_dupallocN(gps->dvert); - BKE_gpencil_stroke_weights_duplicate(gps, gpsn); - } - /* duplicate triangle information */ - gpsn->triangles = MEM_dupallocN(gps->triangles); - /* append stroke to frame */ - BLI_addtail(&gpf->strokes, gpsn); - } - - /* if no strokes (i.e. new frame) added, free gpf */ - if (BLI_listbase_is_empty(&gpf->strokes)) - BKE_gpencil_layer_delframe(gpld, gpf); - } - - /* unapply offset from buffer-frame */ - gpfs->framenum -= offset; - } - } - - /* clean up */ - ANIM_animdata_freelist(&anim_data); - return true; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + Scene *scene = ac->scene; + bool no_name = false; + int offset = 0; + + /* check if buffer is empty */ + if (BLI_listbase_is_empty(&gp_anim_copybuf)) { + BKE_report(ac->reports, RPT_ERROR, "No data in buffer to paste"); + return false; + } + + /* check if single channel in buffer (disregard names if so) */ + if (gp_anim_copybuf.first == gp_anim_copybuf.last) { + no_name = true; + } + + /* methods of offset (eKeyPasteOffset) */ + switch (offset_mode) { + case KEYFRAME_PASTE_OFFSET_CFRA_START: + offset = (CFRA - gp_anim_copy_firstframe); + break; + case KEYFRAME_PASTE_OFFSET_CFRA_END: + offset = (CFRA - gp_anim_copy_lastframe); + break; + case KEYFRAME_PASTE_OFFSET_CFRA_RELATIVE: + offset = (CFRA - gp_anim_copy_cfra); + break; + case KEYFRAME_PASTE_OFFSET_NONE: + offset = 0; + break; + } + + /* filter data */ + // TODO: try doing it with selection, then without selection imits + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | + ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* from selected channels */ + for (ale = anim_data.first; ale; ale = ale->next) { + bGPDlayer *gpld = (bGPDlayer *)ale->data; + bGPDlayer *gpls = NULL; + bGPDframe *gpfs, *gpf; + + /* find suitable layer from buffer to use to paste from */ + for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) { + /* check if layer name matches */ + if ((no_name) || STREQ(gpls->info, gpld->info)) { + break; + } + } + + /* this situation might occur! */ + if (gpls == NULL) + continue; + + /* add frames from buffer */ + for (gpfs = gpls->frames.first; gpfs; gpfs = gpfs->next) { + /* temporarily apply offset to buffer-frame while copying */ + gpfs->framenum += offset; + + /* get frame to copy data into (if no frame returned, then just ignore) */ + gpf = BKE_gpencil_layer_getframe(gpld, gpfs->framenum, GP_GETFRAME_ADD_NEW); + if (gpf) { + bGPDstroke *gps, *gpsn; + + /* This should be the right frame... as it may be a pre-existing frame, + * must make sure that only compatible stroke types get copied over + * - We cannot just add a duplicate frame, as that would cause errors + * - For now, we don't check if the types will be compatible since we + * don't have enough info to do so. Instead, we simply just paste, + * if it works, it will show up. + */ + for (gps = gpfs->strokes.first; gps; gps = gps->next) { + /* make a copy of stroke, then of its points array */ + gpsn = MEM_dupallocN(gps); + gpsn->points = MEM_dupallocN(gps->points); + if (gps->dvert != NULL) { + gpsn->dvert = MEM_dupallocN(gps->dvert); + BKE_gpencil_stroke_weights_duplicate(gps, gpsn); + } + /* duplicate triangle information */ + gpsn->triangles = MEM_dupallocN(gps->triangles); + /* append stroke to frame */ + BLI_addtail(&gpf->strokes, gpsn); + } + + /* if no strokes (i.e. new frame) added, free gpf */ + if (BLI_listbase_is_empty(&gpf->strokes)) + BKE_gpencil_layer_delframe(gpld, gpf); + } + + /* unapply offset from buffer-frame */ + gpfs->framenum -= offset; + } + } + + /* clean up */ + ANIM_animdata_freelist(&anim_data); + return true; } /* -------------------------------------- */ @@ -517,53 +513,54 @@ bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode) static short snap_gpf_nearest(bGPDframe *UNUSED(gpf), Scene *UNUSED(scene)) { #if 0 /* note: gpf->framenum is already an int! */ - if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)(floor(gpf->framenum + 0.5)); + if (gpf->flag & GP_FRAME_SELECT) + gpf->framenum = (int)(floor(gpf->framenum + 0.5)); #endif - return 0; + return 0; } static short snap_gpf_nearestsec(bGPDframe *gpf, Scene *scene) { - float secf = (float)FPS; - if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)(floorf(gpf->framenum / secf + 0.5f) * secf); - return 0; + float secf = (float)FPS; + if (gpf->flag & GP_FRAME_SELECT) + gpf->framenum = (int)(floorf(gpf->framenum / secf + 0.5f) * secf); + return 0; } static short snap_gpf_cframe(bGPDframe *gpf, Scene *scene) { - if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)CFRA; - return 0; + if (gpf->flag & GP_FRAME_SELECT) + gpf->framenum = (int)CFRA; + return 0; } static short snap_gpf_nearmarker(bGPDframe *gpf, Scene *scene) { - if (gpf->flag & GP_FRAME_SELECT) - gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers, (float)gpf->framenum); - return 0; + if (gpf->flag & GP_FRAME_SELECT) + gpf->framenum = (int)ED_markers_find_nearest_marker_time(&scene->markers, + (float)gpf->framenum); + return 0; } /* snap selected frames to ... */ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) { - switch (mode) { - case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); - break; - case SNAP_KEYS_CURFRAME: /* snap to current frame */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe); - break; - case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); - break; - case SNAP_KEYS_NEARSEC: /* snap to nearest second */ - ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); - break; - default: /* just in case */ - break; - } + switch (mode) { + case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */ + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearest); + break; + case SNAP_KEYS_CURFRAME: /* snap to current frame */ + ED_gplayer_frames_looper(gpl, scene, snap_gpf_cframe); + break; + case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */ + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearmarker); + break; + case SNAP_KEYS_NEARSEC: /* snap to nearest second */ + ED_gplayer_frames_looper(gpl, scene, snap_gpf_nearestsec); + break; + default: /* just in case */ + break; + } } /* -------------------------------------- */ @@ -571,105 +568,104 @@ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode) static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene) { - int diff; + int diff; - if (gpf->flag & GP_FRAME_SELECT) { - diff = CFRA - gpf->framenum; - gpf->framenum = CFRA + diff; - } + if (gpf->flag & GP_FRAME_SELECT) { + diff = CFRA - gpf->framenum; + gpf->framenum = CFRA + diff; + } - return 0; + return 0; } static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene)) { - int diff; + int diff; - if (gpf->flag & GP_FRAME_SELECT) { - diff = -gpf->framenum; - gpf->framenum = diff; - } + if (gpf->flag & GP_FRAME_SELECT) { + diff = -gpf->framenum; + gpf->framenum = diff; + } - return 0; + return 0; } static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene)) { - int diff; + int diff; - /* NOTE: since we can't really do this, we just do the same as for yaxis... */ - if (gpf->flag & GP_FRAME_SELECT) { - diff = -gpf->framenum; - gpf->framenum = diff; - } + /* NOTE: since we can't really do this, we just do the same as for yaxis... */ + if (gpf->flag & GP_FRAME_SELECT) { + diff = -gpf->framenum; + gpf->framenum = diff; + } - return 0; + return 0; } static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene) { - static TimeMarker *marker; - static short initialized = 0; - int diff; - - /* In order for this mirror function to work without - * any extra arguments being added, we use the case - * of bezt==NULL to denote that we should find the - * marker to mirror over. The static pointer is safe - * to use this way, as it will be set to null after - * each cycle in which this is called. - */ - - if (gpf) { - /* mirroring time */ - if ((gpf->flag & GP_FRAME_SELECT) && (marker)) { - diff = (marker->frame - gpf->framenum); - gpf->framenum = (marker->frame + diff); - } - } - else { - /* initialization time */ - if (initialized) { - /* reset everything for safety */ - marker = NULL; - initialized = 0; - } - else { - /* try to find a marker */ - marker = ED_markers_get_first_selected(&scene->markers); - if (marker) { - initialized = 1; - } - } - } - - return 0; + static TimeMarker *marker; + static short initialized = 0; + int diff; + + /* In order for this mirror function to work without + * any extra arguments being added, we use the case + * of bezt==NULL to denote that we should find the + * marker to mirror over. The static pointer is safe + * to use this way, as it will be set to null after + * each cycle in which this is called. + */ + + if (gpf) { + /* mirroring time */ + if ((gpf->flag & GP_FRAME_SELECT) && (marker)) { + diff = (marker->frame - gpf->framenum); + gpf->framenum = (marker->frame + diff); + } + } + else { + /* initialization time */ + if (initialized) { + /* reset everything for safety */ + marker = NULL; + initialized = 0; + } + else { + /* try to find a marker */ + marker = ED_markers_get_first_selected(&scene->markers); + if (marker) { + initialized = 1; + } + } + } + + return 0; } - /* mirror selected gp-frames on... */ // TODO: mirror over a specific time void ED_gplayer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode) { - switch (mode) { - case MIRROR_KEYS_CURFRAME: /* mirror over current frame */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe); - break; - case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); - break; - case MIRROR_KEYS_XAXIS: /* mirror over value 0 */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis); - break; - case MIRROR_KEYS_MARKER: /* mirror over marker */ - mirror_gpf_marker(NULL, NULL); - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker); - mirror_gpf_marker(NULL, NULL); - break; - default: /* just in case */ - ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); - break; - } + switch (mode) { + case MIRROR_KEYS_CURFRAME: /* mirror over current frame */ + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe); + break; + case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */ + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); + break; + case MIRROR_KEYS_XAXIS: /* mirror over value 0 */ + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis); + break; + case MIRROR_KEYS_MARKER: /* mirror over marker */ + mirror_gpf_marker(NULL, NULL); + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_marker); + mirror_gpf_marker(NULL, NULL); + break; + default: /* just in case */ + ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis); + break; + } } /* ***************************************** */ |