Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/gpencil/editaction_gpencil.c')
-rw-r--r--source/blender/editors/gpencil/editaction_gpencil.c852
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;
+ }
}
/* ***************************************** */