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.c259
1 files changed, 130 insertions, 129 deletions
diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c
index a2ba6216f9c..09a72c10457 100644
--- a/source/blender/editors/gpencil/editaction_gpencil.c
+++ b/source/blender/editors/gpencil/editaction_gpencil.c
@@ -44,11 +44,15 @@
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
+#include "BKE_report.h"
+#include "ED_anim_api.h"
#include "ED_gpencil.h"
#include "ED_keyframes_edit.h"
#include "ED_markers.h"
+#include "WM_api.h"
+
/* ***************************************** */
/* NOTE ABOUT THIS FILE:
* This file contains code for editing Grease Pencil data in the Action Editor
@@ -268,7 +272,7 @@ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
}
}
-#if 0 // XXX disabled until grease pencil code stabilises again
+
/* -------------------------------------- */
/* Copy and Paste Tools */
/* - The copy/paste buffer currently stores a set of GP_Layers, with temporary
@@ -280,118 +284,155 @@ void ED_gplayer_frames_keytype_set(bGPDlayer *gpl, short type)
*/
/* globals for copy/paste data (like for other copy/paste buffers) */
-ListBase gpcopybuf = {NULL, NULL};
-static int gpcopy_firstframe = 999999999;
+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;
+
/* This function frees any MEM_calloc'ed copy/paste buffer data */
-void free_gpcopybuf()
+void ED_gpencil_anim_copybuf_free(void)
{
- free_gpencil_layers(&gpcopybuf);
+ free_gpencil_layers(&gp_anim_copybuf);
+ BLI_listbase_clear(&gp_anim_copybuf);
- BLI_listbase_clear(&gpcopybuf);
- gpcopy_firstframe = 999999999;
+ 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.
+ *
+ * Returns whether the copy operation was successful or not
*/
-void copy_gpdata()
+bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac)
{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
int filter;
- void *data;
- short datatype;
- /* clear buffer first */
- free_gpcopybuf();
+ Scene *scene = ac->scene;
- /* get data */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_GPENCIL) return;
- /* filter data */
- filter = (ACTFILTER_VISIBLE | ACTFILTER_SEL);
- actdata_filter(&act_data, filter, data, datatype);
+ /* clear buffer first */
+ ED_gpencil_anim_copybuf_free();
- /* assume that each of these is an ipo-block */
- for (ale = act_data.first; ale; ale = ale->next) {
- bGPDlayer *gpls, *gpln;
- bGPDframe *gpf, *gpfn;
-
- /* get new layer to put into buffer */
- gpls = (bGPDlayer *)ale->data;
- gpln = MEM_callocN(sizeof(bGPDlayer), "GPCopyPasteLayer");
-
- BLI_listbase_clear(&gpln->frames);
- BLI_strncpy(gpln->info, gpls->info, sizeof(gpln->info));
-
- BLI_addtail(&gpcopybuf, gpln);
+ /* 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 = gpls->frames.first; gpf; gpf = gpf->next) {
+ 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) {
- /* add frame to buffer */
- gpfn = gpencil_frame_duplicate(gpf);
- BLI_addtail(&gpln->frames, gpfn);
+ /* make a copy of this frame */
+ bGPDframe *new_frame = gpencil_frame_duplicate(gpf);
+ BLI_addtail(&copied_frames, new_frame);
- /* check if this is the earliest frame encountered so far */
- if (gpf->framenum < gpcopy_firstframe)
- gpcopy_firstframe = gpf->framenum;
+ /* 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, gpcopybuf.first, gpcopybuf.last))
- error("Nothing copied to 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;
+ }
- /* free temp memory */
- BLI_freelistN(&act_data);
+ /* report success */
+ return true;
}
-void paste_gpdata(Scene *scene)
+
+/* Pastes keyframes from buffer, and reports success */
+bool ED_gpencil_anim_copybuf_paste(bAnimContext *ac, const short offset_mode)
{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
int filter;
- void *data;
- short datatype;
- const int offset = (CFRA - gpcopy_firstframe);
- short no_name = 0;
+ Scene *scene = ac->scene;
+ bool no_name = false;
+ int offset = 0;
/* check if buffer is empty */
- if (ELEM(NULL, gpcopybuf.first, gpcopybuf.last)) {
- error("No data in buffer to paste");
- return;
+ 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 (gpcopybuf.first == gpcopybuf.last)
- no_name = 1;
+ if (gp_anim_copybuf.first == gp_anim_copybuf.last) {
+ no_name = true;
+ }
- /* get data */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_GPENCIL) return;
+ /* 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 */
- filter = (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT);
- actdata_filter(&act_data, filter, data, datatype);
+ // 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 = act_data.first; ale; ale = ale->next) {
+ 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 = gpcopybuf.first; gpls; gpls = gpls->next) {
+ for (gpls = gp_anim_copybuf.first; gpls; gpls = gpls->next) {
/* check if layer name matches */
- if ((no_name) || STREQ(gpls->info, gpld->info))
+ if ((no_name) || STREQ(gpls->info, gpld->info)) {
break;
+ }
}
/* this situation might occur! */
@@ -407,58 +448,21 @@ void paste_gpdata(Scene *scene)
gpf = gpencil_layer_getframe(gpld, gpfs->framenum, 1);
if (gpf) {
bGPDstroke *gps, *gpsn;
- ScrArea *sa;
-
- /* get area that gp-data comes from */
- //sa = gpencil_data_findowner((bGPdata *)ale->owner);
- sa = NULL;
- /* this should be the right frame... as it may be a pre-existing frame,
+ /* 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
- * - need to check for compatible types to minimize memory usage (copying 'junk' 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,
+ * af it works, it will show up.
*/
for (gps = gpfs->strokes.first; gps; gps = gps->next) {
- short stroke_ok;
+ /* make a copy of stroke, then of its points array */
+ gpsn = MEM_dupallocN(gps);
+ gpsn->points = MEM_dupallocN(gps->points);
- /* if there's an area, check that it supports this type of stroke */
- if (sa) {
- stroke_ok = 0;
-
- /* check if spacetype supports this type of stroke
- * - NOTE: must sync this with gp_paint_initstroke() in gpencil.c
- */
- switch (sa->spacetype) {
- case SPACE_VIEW3D: /* 3D-View: either screen-aligned or 3d-space */
- if ((gps->flag == 0) || (gps->flag & GP_STROKE_3DSPACE))
- stroke_ok = 1;
- break;
-
- case SPACE_NODE: /* Nodes Editor: either screen-aligned or view-aligned */
- case SPACE_IMAGE: /* Image Editor: either screen-aligned or view\image-aligned */
- case SPACE_CLIP: /* Image Editor: either screen-aligned or view\image-aligned */
- if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DSPACE))
- stroke_ok = 1;
- break;
-
- case SPACE_SEQ: /* Sequence Editor: either screen-aligned or view-aligned */
- if ((gps->flag == 0) || (gps->flag & GP_STROKE_2DIMAGE))
- stroke_ok = 1;
- break;
- }
- }
- else
- stroke_ok = 1;
-
- /* if stroke is ok, we make a copy of this stroke and add to frame */
- if (stroke_ok) {
- /* make a copy of stroke, then of its points array */
- gpsn = MEM_dupallocN(gps);
- gpsn->points = MEM_dupallocN(gps->points);
-
- /* append stroke to frame */
- BLI_addtail(&gpf->strokes, gpsn);
- }
+ /* append stroke to frame */
+ BLI_addtail(&gpf->strokes, gpsn);
}
/* if no strokes (i.e. new frame) added, free gpf */
@@ -471,13 +475,10 @@ void paste_gpdata(Scene *scene)
}
}
- /* free temp memory */
- BLI_freelistN(&act_data);
-
- /* undo and redraw stuff */
- BIF_undo_push("Paste Grease Pencil Frames");
+ /* clean up */
+ ANIM_animdata_freelist(&anim_data);
+ return true;
}
-#endif /* XXX disabled until Grease Pencil code stabilises again... */
/* -------------------------------------- */
/* Snap Tools */
@@ -534,7 +535,6 @@ void ED_gplayer_snap_frames(bGPDlayer *gpl, Scene *scene, short mode)
}
}
-#if 0 /* XXX disabled until grease pencil code stabilises again */
/* -------------------------------------- */
/* Mirror Tools */
@@ -544,13 +544,13 @@ static short mirror_gpf_cframe(bGPDframe *gpf, Scene *scene)
if (gpf->flag & GP_FRAME_SELECT) {
diff = CFRA - gpf->framenum;
- gpf->framenum = CFRA;
+ gpf->framenum = CFRA + diff;
}
return 0;
}
-static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *scene)
+static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *UNUSED(scene))
{
int diff;
@@ -562,10 +562,11 @@ static short mirror_gpf_yaxis(bGPDframe *gpf, Scene *scene)
return 0;
}
-static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *scene)
+static short mirror_gpf_xaxis(bGPDframe *gpf, Scene *UNUSED(scene))
{
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;
@@ -616,19 +617,20 @@ static short mirror_gpf_marker(bGPDframe *gpf, Scene *scene)
/* mirror selected gp-frames on... */
-void mirror_gplayer_frames(bGPDlayer *gpl, Scene *scene, short mode)
+// TODO: mirror over a specific time
+void ED_gplayer_mirror_frames(bGPDlayer *gpl, Scene *scene, short mode)
{
switch (mode) {
- case 1: /* mirror over current frame */
+ case MIRROR_KEYS_CURFRAME: /* mirror over current frame */
ED_gplayer_frames_looper(gpl, scene, mirror_gpf_cframe);
break;
- case 2: /* mirror over frame 0 */
+ case MIRROR_KEYS_YAXIS: /* mirror over frame 0 */
ED_gplayer_frames_looper(gpl, scene, mirror_gpf_yaxis);
break;
- case 3: /* mirror over value 0 */
+ case MIRROR_KEYS_XAXIS: /* mirror over value 0 */
ED_gplayer_frames_looper(gpl, scene, mirror_gpf_xaxis);
break;
- case 4: /* mirror over marker */
+ 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);
@@ -640,4 +642,3 @@ void mirror_gplayer_frames(bGPDlayer *gpl, Scene *scene, short mode)
}
/* ***************************************** */
-#endif // XXX disabled until Grease Pencil code stabilises again...