diff --git a/release/scripts/ui/space_dopesheet.py b/release/scripts/ui/space_dopesheet.py index 00e80c664c4..2a3b8184cd2 100644 --- a/release/scripts/ui/space_dopesheet.py +++ b/release/scripts/ui/space_dopesheet.py @@ -20,6 +20,8 @@ import bpy +####################################### +# DopeSheet Filtering # used for DopeSheet, NLA, and Graph Editors def dopesheet_filter(layout, context): @@ -70,6 +72,8 @@ def dopesheet_filter(layout, context): if dopesheet.show_only_group_objects: row.prop(dopesheet, "filter_group", text="") +####################################### +# DopeSheet Editor - General/Standard UI class DOPESHEET_HT_header(bpy.types.Header): bl_space_type = 'DOPESHEET_EDITOR' @@ -92,11 +96,12 @@ class DOPESHEET_HT_header(bpy.types.Header): if st.mode == 'DOPESHEET' or (st.mode == 'ACTION' and st.action != None): sub.menu("DOPESHEET_MT_channel") elif st.mode == 'GPENCIL': - # gpencil Channel menu - pass + sub.menu("DOPESHEET_MT_gpencil_channel") if st.mode != 'GPENCIL': sub.menu("DOPESHEET_MT_key") + else: + sub.menu("DOPESHEET_MT_gpencil_frame") layout.prop(st, "mode", text="") layout.prop(st.dopesheet, "show_summary", text="Summary") @@ -106,7 +111,8 @@ class DOPESHEET_HT_header(bpy.types.Header): elif st.mode in ('ACTION', 'SHAPEKEY'): layout.template_ID(st, "action", new="action.new") - + + # Grease Pencil mode doesn't need snapping, as it's frame-aligned only if st.mode != 'GPENCIL': layout.prop(st, "auto_snap", text="") @@ -171,13 +177,15 @@ class DOPESHEET_MT_select(bpy.types.Menu): layout.operator("action.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN' layout.operator("action.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN' + + # FIXME: grease pencil mode isn't supported for these yet, so skip for that mode only + if context.space_data.mode != 'GPENCIL': + layout.separator() + layout.operator("action.select_more") + layout.operator("action.select_less") - layout.separator() - layout.operator("action.select_more") - layout.operator("action.select_less") - - layout.separator() - layout.operator("action.select_linked") + layout.separator() + layout.operator("action.select_linked") class DOPESHEET_MT_marker(bpy.types.Menu): bl_label = "Marker" @@ -203,6 +211,9 @@ class DOPESHEET_MT_marker(bpy.types.Menu): layout.separator() layout.prop(st, "show_pose_markers") +####################################### +# Keyframe Editing + class DOPESHEET_MT_channel(bpy.types.Menu): bl_label = "Channel" @@ -266,7 +277,6 @@ class DOPESHEET_MT_key(bpy.types.Menu): layout.operator("action.copy") layout.operator("action.paste") - class DOPESHEET_MT_key_transform(bpy.types.Menu): bl_label = "Transform" @@ -279,6 +289,56 @@ class DOPESHEET_MT_key_transform(bpy.types.Menu): layout.operator("transform.transform", text="Slide").mode = 'TIME_SLIDE' layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE' +####################################### +# Grease Pencil Editing + +class DOPESHEET_MT_gpencil_channel(bpy.types.Menu): + bl_label = "Channel" + + def draw(self, context): + layout = self.layout + + layout.operator_context = 'INVOKE_REGION_CHANNELS' + + layout.column() + layout.operator("anim.channels_delete") + + layout.separator() + layout.operator("anim.channels_setting_toggle") + layout.operator("anim.channels_setting_enable") + layout.operator("anim.channels_setting_disable") + + layout.separator() + layout.operator("anim.channels_editable_toggle") + + # XXX: to be enabled when these are ready for use! + #layout.separator() + #layout.operator("anim.channels_expand") + #layout.operator("anim.channels_collapse") + + #layout.separator() + #layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") + +class DOPESHEET_MT_gpencil_frame(bpy.types.Menu): + bl_label = "Frame" + + def draw(self, context): + layout = self.layout + + layout.column() + layout.menu("DOPESHEET_MT_key_transform", text="Transform") + + #layout.operator_menu_enum("action.snap", "type", text="Snap") + #layout.operator_menu_enum("action.mirror", "type", text="Mirror") + + layout.separator() + layout.operator("action.duplicate") + layout.operator("action.delete") + + #layout.separator() + #layout.operator("action.copy") + #layout.operator("action.paste") + def register(): pass diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 298fd9102ec..66f574a4b70 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -49,6 +49,7 @@ #include "DNA_meta_types.h" #include "DNA_node_types.h" #include "DNA_world_types.h" +#include "DNA_gpencil_types.h" #include "RNA_access.h" @@ -2404,126 +2405,157 @@ static bAnimChannelType ACF_SHAPEKEY= acf_shapekey_setting_ptr /* pointer for setting */ }; -/* Grease Pencil entries ------------------------------------------- */ -// XXX ... this is currently not restored yet +/* GPencil Datablock ------------------------------------------- */ -#if 0 -static void dummy_olddraw_gpencil () +/* get backdrop color for gpencil datablock widget */ +static void acf_gpd_color(bAnimContext *UNUSED(ac), bAnimListElem *ale, float *color) { - /* determine what needs to be drawn */ - switch (ale->type) { - case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */ - { - bGPdata *gpd = (bGPdata *)ale->data; - ScrArea *sa = (ScrArea *)ale->owner; // XXX depreceated... + /* highlight only for datablock channels */ + //if (ale->flag & AGRP_ACTIVE) + // UI_GetThemeColorShade3fv(TH_GROUP_ACTIVE, 10, color); + //else + UI_GetThemeColorShade3fv(TH_GROUP, 20, color); +} + +// TODO: just get this from RNA? +static int acf_gpd_icon(bAnimListElem *UNUSED(ale)) +{ + return ICON_GREASEPENCIL; +} + +/* check if some setting exists for this channel */ +static short acf_gpd_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting) +{ + switch (setting) { + /* only select and expand supported */ + case ACHANNEL_SETTING_SELECT: + case ACHANNEL_SETTING_EXPAND: + return 1; - indent = 0; - group= 3; - - /* only show expand if there are any channels */ - if (gpd->layers.first) { - if (gpd->flag & GP_DATA_EXPAND) - expand = ICON_TRIA_DOWN; - else - expand = ICON_TRIA_RIGHT; - } - - switch (sa->spacetype) { - case SPACE_VIEW3D: - { - /* this shouldn't cause any overflow... */ - //sprintf(name, "View3D:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func.. - strcpy(name, "View3D"); - special= ICON_VIEW3D; - } - break; - case SPACE_NODE: - { - SpaceNode *snode= sa->spacedata.first; - char treetype[12]; - - if (snode->treetype == 1) - strcpy(treetype, "Composite"); - else - strcpy(treetype, "Material"); - sprintf(name, "Nodes:%s", treetype); - - special= ICON_NODETREE; - } - break; - case SPACE_SEQ: - { - SpaceSeq *sseq= sa->spacedata.first; - char imgpreview[10]; - - switch (sseq->mainb) { - case 1: sprintf(imgpreview, "Image..."); break; - case 2: sprintf(imgpreview, "Luma..."); break; - case 3: sprintf(imgpreview, "Chroma..."); break; - case 4: sprintf(imgpreview, "Histogram"); break; - - default: sprintf(imgpreview, "Sequence"); break; - } - sprintf(name, "Sequencer:%s", imgpreview); - - special= ICON_SEQUENCE; - } - break; - case SPACE_IMAGE: - { - SpaceImage *sima= sa->spacedata.first; - - if (sima->image) - sprintf(name, "Image:%s", sima->image->id.name+2); - else - strcpy(name, "Image:"); - - special= ICON_IMAGE_COL; - } - break; - - default: - { - sprintf(name, ""); - special= -1; - } - break; - } - } - break; - case ANIMTYPE_GPLAYER: /* gpencil layer */ - { - bGPDlayer *gpl = (bGPDlayer *)ale->data; - - indent = 0; - special = -1; - expand = -1; - group = 1; - - if (EDITABLE_GPL(gpl)) - protect = ICON_UNLOCKED; - else - protect = ICON_LOCKED; - - if (gpl->flag & GP_LAYER_HIDE) - mute = ICON_MUTE_IPO_ON; - else - mute = ICON_MUTE_IPO_OFF; - - sel = SEL_GPL(gpl); - BLI_snprintf(name, 32, gpl->info); - } - break; - } - - if (group == 3) { - /* only for gp-data channels */ - UI_ThemeColorShade(TH_GROUP, 20); - uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8)); - gl_round_box(GL_POLYGON, x+offset, yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8); + default: + return 0; } } -#endif + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_gpd_setting_flag(bAnimContext *ac, int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return AGRP_SELECTED; + + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return GP_DATA_EXPAND; + } + + /* this shouldn't happen */ + return 0; +} + +/* get pointer to the setting */ +static void *acf_gpd_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) +{ + bGPdata *gpd= (bGPdata *)ale->data; + + /* all flags are just in gpd->flag for now... */ + GET_ACF_FLAG_PTR(gpd->flag); +} + +/* gpencil datablock type define */ +static bAnimChannelType ACF_GPD = +{ + "GPencil Datablock", /* type name */ + + acf_gpd_color, /* backdrop color */ + acf_group_backdrop, /* backdrop */ + acf_generic_indention_0, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_gpd_icon, /* icon */ + + acf_gpd_setting_valid, /* has setting */ + acf_gpd_setting_flag, /* flag for setting */ + acf_gpd_setting_ptr /* pointer for setting */ +}; + +/* GPencil Layer ------------------------------------------- */ + +/* name for grase pencil layer entries */ +static void acf_gpl_name(bAnimListElem *ale, char *name) +{ + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + if (gpl && name) + sprintf(name, gpl->info); +} + +/* check if some setting exists for this channel */ +static short acf_gpl_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) +{ + switch (setting) { + /* unsupported */ + case ACHANNEL_SETTING_EXPAND: /* gpencil layers are more like F-Curves than groups */ + case ACHANNEL_SETTING_VISIBLE: /* graph editor only */ + return 0; + + /* always available */ + default: + return 1; + } +} + +/* get the appropriate flag(s) for the setting when it is valid */ +static int acf_gpl_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg) +{ + /* clear extra return data first */ + *neg= 0; + + switch (setting) { + case ACHANNEL_SETTING_SELECT: /* selected */ + return GP_LAYER_SELECT; + + case ACHANNEL_SETTING_MUTE: /* muted */ + return GP_LAYER_HIDE; + + case ACHANNEL_SETTING_PROTECT: /* protected */ + //*neg= 1; - if we change this to edtiability + return GP_LAYER_LOCKED; + + default: /* unsupported */ + return 0; + } +} + +/* get pointer to the setting */ +static void *acf_gpl_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type) +{ + bGPDlayer *gpl= (bGPDlayer *)ale->data; + + /* all flags are just in agrp->flag for now... */ + GET_ACF_FLAG_PTR(gpl->flag); +} + +/* grease pencil layer type define */ +static bAnimChannelType ACF_GPL = +{ + "GPencil Layer", /* type name */ + + acf_generic_channel_color, /* backdrop color */ + acf_generic_channel_backdrop, /* backdrop */ + acf_generic_indention_flexible, /* indent level */ + acf_generic_group_offset, /* offset */ + + acf_gpl_name, /* name */ + NULL, /* icon */ + + acf_gpl_setting_valid, /* has setting */ + acf_gpl_setting_flag, /* flag for setting */ + acf_gpl_setting_ptr /* pointer for setting */ +}; /* *********************************************** */ /* Type Registration and General Access */ @@ -2574,9 +2606,8 @@ void ANIM_init_channel_typeinfo_data (void) animchannelTypeInfo[type++]= &ACF_SHAPEKEY; /* ShapeKey */ - // XXX not restored yet - animchannelTypeInfo[type++]= NULL; /* Grease Pencil Datablock */ - animchannelTypeInfo[type++]= NULL; /* Grease Pencil Layer */ + animchannelTypeInfo[type++]= &ACF_GPD; /* Grease Pencil Datablock */ + animchannelTypeInfo[type++]= &ACF_GPL; /* Grease Pencil Layer */ // TODO: these types still need to be implemented!!! // probably need a few extra flags for these special cases... diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 319f80404b4..6701729f34f 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -245,6 +245,11 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype, sel= ACHANNEL_SETFLAG_CLEAR; } break; + + case ANIMTYPE_GPLAYER: + if (ale->flag & GP_LAYER_SELECT) + sel= ACHANNEL_SETFLAG_CLEAR; + break; } } } @@ -332,6 +337,14 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype, } } break; + + case ANIMTYPE_GPLAYER: + { + bGPDlayer *gpl = (bGPDlayer *)ale->data; + + ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT); + } + break; } } @@ -1000,10 +1013,10 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op) rearrange_driver_channels(&ac, adt, mode); break; -#if 0 case ANIMCONT_GPENCIL: /* Grease Pencil channels */ + // FIXME: this case probably needs to get moved out of here or treated specially... + printf("grease pencil not supported for moving yet\n"); break; -#endif case ANIMCONT_SHAPEKEY: // DOUBLE CHECK ME... @@ -2047,7 +2060,9 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i { bGPdata *gpd= (bGPdata *)ale->data; - /* toggle expand */ + /* toggle expand + * - although the triangle widget already allows this, the whole channel can also be used for this purpose + */ gpd->flag ^= GP_DATA_EXPAND; notifierFlags |= (ND_ANIMCHAN|NA_EDITED); @@ -2055,29 +2070,20 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i break; case ANIMTYPE_GPLAYER: { -#if 0 // XXX future of this is unclear - bGPdata *gpd= (bGPdata *)ale->owner; // xxx depreceated bGPDlayer *gpl= (bGPDlayer *)ale->data; - if (x >= (ACHANNEL_NAMEWIDTH-16)) { - /* toggle lock */ - gpl->flag ^= GP_LAYER_LOCKED; + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* invert selection status of this layer only */ + gpl->flag ^= GP_LAYER_SELECT; } - else if (x >= (ACHANNEL_NAMEWIDTH-32)) { - /* toggle hide */ - gpl->flag ^= GP_LAYER_HIDE; + else { + /* select layer by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + gpl->flag |= GP_LAYER_SELECT; } - else { - /* select/deselect */ - //if (G.qual & LR_SHIFTKEY) { - //select_gplayer_channel(gpd, gpl, SELECT_INVERT); - //} - //else { - //deselect_gpencil_layers(data, 0); - //select_gplayer_channel(gpd, gpl, SELECT_INVERT); - //} - } -#endif // XXX future of this is unclear + + notifierFlags |= (ND_ANIMCHAN|NA_EDITED); } break; default: diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index c61adcd6518..1d54a7e5195 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -79,6 +79,7 @@ #include "BKE_global.h" #include "BKE_group.h" #include "BKE_key.h" +#include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_sequencer.h" @@ -145,9 +146,11 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction) return 1; case SACTCONT_GPENCIL: /* Grease Pencil */ // XXX review how this mode is handled... - ac->datatype=ANIMCONT_GPENCIL; - //ac->data= CTX_wm_screen(C); // FIXME: add that dopesheet type thing here! - ac->data= NULL; // !!! + /* update scene-pointer (no need to check for pinning yet, as not implemented) */ + saction->ads.source= (ID *)ac->scene; + + ac->datatype= ANIMCONT_GPENCIL; + ac->data= &saction->ads; ac->mode= saction->mode; return 1; @@ -1181,38 +1184,28 @@ static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key return items; } -#if 0 -// FIXME: switch this to use the bDopeSheet... -static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode) +/* Grab all Grase Pencil datablocks in file */ +// TODO: should this be amalgamated with the dopesheet filtering code? +static int animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int filter_mode) { bAnimListElem *ale; - ScrArea *sa, *curarea; bGPdata *gpd; bGPDlayer *gpl; int items = 0; /* check if filtering types are appropriate */ + if (!(filter_mode & (ANIMFILTER_ACTGROUPED|ANIMFILTER_CURVESONLY))) { - /* special hack for fullscreen area (which must be this one then): - * - we use the curarea->full as screen to get spaces from, since the - * old (pre-fullscreen) screen was stored there... - * - this is needed as all data would otherwise disappear - */ - // XXX need to get new alternative for curarea - if ((curarea->full) && (curarea->spacetype==SPACE_ACTION)) - sc= curarea->full; - - /* loop over spaces in current screen, finding gpd blocks (could be slow!) */ - for (sa= sc->areabase.first; sa; sa= sa->next) { - /* try to get gp data */ - // XXX need to put back grease pencil api... - gpd= gpencil_data_get_active(sa); - if (gpd == NULL) continue; + /* for now, grab grease pencil datablocks directly from main*/ + for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) { + /* only show if gpd is used by something... */ + if (ID_REAL_USERS(gpd) < 1) + continue; /* add gpd as channel too (if for drawing, and it has layers) */ if ((filter_mode & ANIMFILTER_CHANNELS) && (gpd->layers.first)) { /* add to list */ - ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA); + ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, NULL, ANIMTYPE_NONE, NULL); if (ale) { BLI_addtail(anim_data, ale); items++; @@ -1228,7 +1221,7 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter /* only if editable */ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) { /* add to list */ - ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK); + ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK, (ID*)gpd); if (ale) { BLI_addtail(anim_data, ale); items++; @@ -1243,7 +1236,6 @@ static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter /* return the number of items added to the list */ return items; } -#endif /* NOTE: owner_id is either material, lamp, or world block, which is the direct owner of the texture stack in question */ static int animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode) @@ -2591,7 +2583,7 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode case ANIMCONT_GPENCIL: { - //items= animdata_filter_gpencil(anim_data, data, filter_mode); + items= animdata_filter_gpencil(anim_data, data, filter_mode); } break; diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 5e7e071954c..12c4baaaa87 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -137,6 +137,49 @@ static void nupdate_ak_bezt (void *node, void *data) ak->key_type= BEZT_KEYTYPE_KEYFRAME; } +/* ......... */ + +/* Comparator callback used for ActKeyColumns and GPencil frame */ +static short compare_ak_gpframe (void *node, void *data) +{ + ActKeyColumn *ak= (ActKeyColumn *)node; + bGPDframe *gpf= (bGPDframe *)data; + + if (gpf->framenum < ak->cfra) + return -1; + else if (gpf->framenum > ak->cfra) + return 1; + else + return 0; +} + +/* New node callback used for building ActKeyColumns from GPencil frames */ +static DLRBT_Node *nalloc_ak_gpframe (void *data) +{ + ActKeyColumn *ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF"); + bGPDframe *gpf= (bGPDframe *)data; + + /* store settings based on state of BezTriple */ + ak->cfra= gpf->framenum; + ak->sel= (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0; + + /* set 'modified', since this is used to identify long keyframes */ + ak->modified = 1; + + return (DLRBT_Node *)ak; +} + +/* Node updater callback used for building ActKeyColumns from GPencil frames */ +static void nupdate_ak_gpframe (void *node, void *data) +{ + ActKeyColumn *ak= (ActKeyColumn *)node; + bGPDframe *gpf= (bGPDframe *)data; + + /* set selection status and 'touched' status */ + if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT; + ak->modified += 1; +} + /* --------------- */ /* Add the given BezTriple to the given 'list' of Keyframes */ @@ -148,6 +191,15 @@ static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt) BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt); } +/* Add the given GPencil Frame to the given 'list' of Keyframes */ +static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf) +{ + if ELEM(NULL, keys, gpf) + return; + else + BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf); +} + /* ActBeztColumns (Helpers for Long Keyframes) ------------------------------ */ /* maximum size of default buffer for BezTriple columns */ @@ -917,23 +969,11 @@ void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys) { bGPDframe *gpf; - ActKeyColumn *ak; if (gpl && keys) { - /* loop over frames, converting directly to 'keyframes' (should be in order too) */ - for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - ak= MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn"); - BLI_addtail((ListBase *)keys, ak); - - ak->cfra= (float)gpf->framenum; - ak->modified = 1; - ak->key_type= 0; - - if (gpf->flag & GP_FRAME_SELECT) - ak->sel = SELECT; - else - ak->sel = 0; - } + /* although the frames should already be in an ordered list, they are not suitable for displaying yet */ + for (gpf= gpl->frames.first; gpf; gpf= gpf->next) + add_gpframe_to_keycolumns_list(keys, gpf); } } diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index 0ee8b914205..643b6c7082f 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -31,21 +31,24 @@ #include #include -#include "BLI_math.h" +#include "MEM_guardedalloc.h" + #include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_gpencil_types.h" +#include "DNA_scene_types.h" + +#include "BKE_fcurve.h" +#include "BKE_gpencil.h" + +#include "ED_anim_api.h" +#include "ED_gpencil.h" +#include "ED_keyframes_edit.h" #include "gpencil_intern.h" -#if 0 // XXX disabled until grease pencil code stabilises again - -/* XXX */ -static void actdata_filter() {} // is now ANIM_animdata_filter() -static void BIF_undo_push() {} -static void error() {} -static void *get_action_context() {return NULL;} // is now ANIM_animdata_get_context() -/* XXX */ - - /* ***************************************** */ /* NOTE ABOUT THIS FILE: * This file contains code for editing Grease Pencil data in the Action Editor @@ -126,6 +129,9 @@ short is_gplayer_frame_selected (bGPDlayer *gpl) /* 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; @@ -160,31 +166,19 @@ void set_gplayer_frame_selection (bGPDlayer *gpl, short mode) /* error checking */ if (gpl == NULL) return; - - /* convert mode to select_mode */ - switch (mode) { - case 2: - mode= SELECT_INVERT; - break; - case 1: - mode= SELECT_ADD; - break; - case 0: - mode= SELECT_SUBTRACT; - break; - default: - return; - } /* now call the standard function */ - select_gpencil_frames (gpl, mode); + select_gpencil_frames(gpl, mode); } /* select the frame in this layer that occurs on this frame (there should only be one at most) */ void select_gpencil_frame (bGPDlayer *gpl, int selx, short select_mode) { bGPDframe *gpf; - + + if (gpl == NULL) + return; + /* search through frames for a match */ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { /* there should only be one frame with this frame-number */ @@ -200,6 +194,9 @@ void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short se { bGPDframe *gpf; + 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)) @@ -207,6 +204,7 @@ void borderselect_gplayer_frames (bGPDlayer *gpl, float min, float max, short se } } +#if 0 // XXX disabled until grease pencil code stabilises again /* De-selects or inverts the selection of Layers for a grease-pencil block * mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all @@ -252,9 +250,12 @@ void deselect_gpencil_layers (void *data, short mode) BLI_freelistN(&act_data); } +#endif // XXX disabled until Grease Pencil code stabilises again... + /* ***************************************** */ /* Frame Editing Tools */ +#if 0 // XXX disabled until grease pencil code stabilises again /* Delete selected grease-pencil layers */ void delete_gpencil_layers (void) { @@ -291,6 +292,7 @@ void delete_gpencil_layers (void) BIF_undo_push("Delete GPencil Layers"); } +#endif // XXX disabled until Grease Pencil code stabilises again... /* Delete selected frames */ void delete_gplayer_frames (bGPDlayer *gpl) @@ -336,6 +338,7 @@ void duplicate_gplayer_frames (bGPDlayer *gpl) } } +#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 diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 78edcc05586..92c090beb8a 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -29,6 +29,7 @@ #define ED_GPENCIL_H struct ListBase; +struct bContext; struct bScreen; struct ScrArea; struct ARegion; @@ -80,5 +81,27 @@ void draw_gpencil_view3d_ext(struct Scene *scene, struct View3D *v3d, struct ARe void gpencil_panel_standard(const struct bContext *C, struct Panel *pa); +/* ----------- Grease-Pencil AnimEdit API ------------------ */ + +void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel); + +void deselect_gpencil_layers(void *data, short select_mode); + +short is_gplayer_frame_selected(struct bGPDlayer *gpl); +void set_gplayer_frame_selection(struct bGPDlayer *gpl, short mode); +void select_gpencil_frames(struct bGPDlayer *gpl, short select_mode); +void select_gpencil_frame(struct bGPDlayer *gpl, int selx, short select_mode); +void borderselect_gplayer_frames(struct bGPDlayer *gpl, float min, float max, short select_mode); + +void delete_gpencil_layers(void); +void delete_gplayer_frames(struct bGPDlayer *gpl); +void duplicate_gplayer_frames(struct bGPDlayer *gpd); + +void free_gpcopybuf(void); +void copy_gpdata(void); +void paste_gpdata(void); + +void snap_gplayer_frames(struct bGPDlayer *gpl, short mode); +void mirror_gplayer_frames(struct bGPDlayer *gpl, short mode); #endif /* ED_GPENCIL_H */ diff --git a/source/blender/editors/space_action/SConscript b/source/blender/editors/space_action/SConscript index 9ef42882b26..2e9a79db04a 100644 --- a/source/blender/editors/space_action/SConscript +++ b/source/blender/editors/space_action/SConscript @@ -6,4 +6,4 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' -env.BlenderLib ( 'bf_editors_space_action', sources, Split(incs), [], libtype=['core'], priority=[80] ) +env.BlenderLib ( 'bf_editors_space_action', sources, Split(incs), [], libtype=['core'], priority=[40] ) diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index c97ed67a45b..888c372f555 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -38,6 +38,7 @@ #include "BLI_utildefines.h" #include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -54,6 +55,7 @@ #include "UI_view2d.h" #include "ED_anim_api.h" +#include "ED_gpencil.h" #include "ED_keyframing.h" #include "ED_keyframes_edit.h" #include "ED_screen.h" @@ -522,10 +524,10 @@ static void duplicate_action_keys (bAnimContext *ac) /* loop through filtered data and delete selected keys */ for (ale= anim_data.first; ale; ale= ale->next) { - //if (ale->type == ANIMTYPE_GPLAYER) - // delete_gplayer_frames((bGPDlayer *)ale->data); - //else + if (ale->type == ANIMTYPE_FCURVE) duplicate_fcurve_keys((FCurve *)ale->key_data); + else + duplicate_gplayer_frames((bGPDlayer *)ale->data); } /* free filtered list */ @@ -611,8 +613,8 @@ static void delete_action_keys (bAnimContext *ac) if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) ANIM_fcurve_delete_from_animdata(ac, adt, fcu); } - //else - // delete_gplayer_frames((bGPDlayer *)ale->data); + else + delete_gplayer_frames((bGPDlayer *)ale->data); } /* free filtered list */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 26990878e46..ea9ef7f8ee6 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -37,6 +37,7 @@ #include "BLI_utildefines.h" #include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -50,6 +51,7 @@ #include "UI_view2d.h" #include "ED_anim_api.h" +#include "ED_gpencil.h" #include "ED_keyframes_draw.h" #include "ED_keyframes_edit.h" #include "ED_markers.h" @@ -75,10 +77,7 @@ * - This is called by the deselect all operator, as well as other ones! * * - test: check if select or deselect all - * - sel: how to select keyframes - * 0 = deselect - * 1 = select - * 2 = invert + * - sel: how to select keyframes (SELECT_*) */ static void deselect_action_keys (bAnimContext *ac, short test, short sel) { @@ -105,10 +104,10 @@ static void deselect_action_keys (bAnimContext *ac, short test, short sel) if (test) { for (ale= anim_data.first; ale; ale= ale->next) { if (ale->type == ANIMTYPE_GPLAYER) { - //if (is_gplayer_frame_selected(ale->data)) { - // sel= 0; - // break; - //} + if (is_gplayer_frame_selected(ale->data)) { + sel= SELECT_SUBTRACT; + break; + } } else { if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) { @@ -124,10 +123,10 @@ static void deselect_action_keys (bAnimContext *ac, short test, short sel) /* Now set the flags */ for (ale= anim_data.first; ale; ale= ale->next) { - //if (ale->type == ACTTYPE_GPLAYER) - // set_gplayer_frame_selection(ale->data, sel); - //else + if (ale->type == ANIMTYPE_FCURVE) ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL); + else if (ale->type == ANIMTYPE_GPLAYER) + set_gplayer_frame_selection(ale->data, sel); } /* Cleanup */ @@ -254,10 +253,10 @@ static void borderselect_action (bAnimContext *ac, rcti rect, short mode, short !((ymax < rectf.ymin) || (ymin > rectf.ymax)) ) { /* loop over data selecting */ - //if (ale->type == ANIMTYPE_GPLAYER) - // borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); - //else + if (ale->type == ANIMTYPE_FCURVE) ANIM_animchannel_keyframes_loop(&ked, ale, ok_cb, select_cb, NULL, filterflag); + else if (ale->type == ANIMTYPE_GPLAYER) + borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); } /* set minimum extent to be the maximum of the next channel */ @@ -395,6 +394,9 @@ static void markers_selectkeys_between (bAnimContext *ac) ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } + else if (ale->type == ANIMTYPE_GPLAYER) { + borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD); + } else { ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } @@ -426,8 +428,8 @@ static void columnselect_action_keys (bAnimContext *ac, short mode) filter= (ANIMFILTER_VISIBLE); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); - //for (ale= anim_data.first; ale; ale= ale->next) - // gplayer_make_cfra_list(ale->data, &elems, 1); + for (ale= anim_data.first; ale; ale= ale->next) + gplayer_make_cfra_list(ale->data, &ked.list, 1); } else { filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY); @@ -482,20 +484,10 @@ static void columnselect_action_keys (bAnimContext *ac, short mode) ked.f1= ce->cfra; /* select elements with frame number matching cfraelem */ - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - -#if 0 // XXX reenable when Grease Pencil stuff is back - if (ale->type == ANIMTYPE_GPLAYER) { - bGPDlayer *gpl= (bGPDlayer *)ale->data; - bGPDframe *gpf; - - for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - if (ecfra == gpf->framenum) - gpf->flag |= GP_FRAME_SELECT; - } - } - //else... -#endif // XXX reenable when Grease Pencil stuff is back + if (ale->type == ANIMTYPE_FCURVE) + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + else if (ale->type == ANIMTYPE_GPLAYER) + select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD); } } @@ -752,7 +744,10 @@ static void actkeys_mselect_single (bAnimContext *ac, bAnimListElem *ale, short ked.f1= selx; /* select the nominated keyframe on the given frame */ - ANIM_animchannel_keyframes_loop(&ked, ale, ok_cb, select_cb, NULL, ds_filter); + if (ale->type == ANIMTYPE_FCURVE) + ANIM_animchannel_keyframes_loop(&ked, ale, ok_cb, select_cb, NULL, ds_filter); + else if (ale->type == ANIMTYPE_GPLAYER) + select_gpencil_frame(ale->data, selx, select_mode); } /* Option 2) Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */ @@ -804,17 +799,18 @@ static void actkeys_mselect_leftright (bAnimContext *ac, short leftright, short ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1); } - //else if (ale->type == ANIMTYPE_GPLAYER) - // borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD); + else if (ale->type == ANIMTYPE_GPLAYER) + borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode); else ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); } /* Sync marker support */ - if((select_mode==SELECT_ADD) && (ac->spacetype==SPACE_ACTION) && ELEM(leftright, ACTKEYS_LRSEL_LEFT, ACTKEYS_LRSEL_RIGHT)) { + // FIXME: this doesn't work for local pose markers! + if ((select_mode==SELECT_ADD) && (ac->spacetype==SPACE_ACTION) && ELEM(leftright, ACTKEYS_LRSEL_LEFT, ACTKEYS_LRSEL_RIGHT)) { SpaceAction *saction= ac->sa->spacedata.first; - if (saction && saction->flag & SACTION_MARKERS_MOVE) { + if (saction && (saction->flag & SACTION_MARKERS_MOVE)) { TimeMarker *marker; for (marker= scene->markers.first; marker; marker= marker->next) { @@ -869,20 +865,10 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se ked.f1= selx; /* select elements with frame number matching cfra */ - ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); - -#if 0 // XXX reenable when Grease Pencil stuff is back - if (ale->type == ANIMTYPE_GPLAYER) { - bGPDlayer *gpl= (bGPDlayer *)ale->data; - bGPDframe *gpf; - - for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - if (ecfra == gpf->framenum) - gpf->flag |= GP_FRAME_SELECT; - } - } - //else... -#endif // XXX reenable when Grease Pencil stuff is back + if (ale->type == ANIMTYPE_FCURVE) + ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL); + else if (ale->type == ANIMTYPE_GPLAYER) + select_gpencil_frame(ale->key_data, selx, select_mode); } /* free elements */ @@ -937,7 +923,6 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, ActKeyColumn *ak, *akn=NULL; /* make list of keyframes */ - // TODO: it would be great if we didn't have to apply this to all the keyframes to do this... BLI_dlrbTree_init(&anim_keys); if (ale->key_data) { @@ -972,27 +957,22 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, /* dopesheet summary covers everything */ summary_to_keylist(ac, &anim_keys, NULL); } - else if (ale->type == ANIMTYPE_GROUP) { + else if (ale->type == ANIMTYPE_GROUP) { + // TODO: why don't we just give groups key_data too? bActionGroup *agrp= (bActionGroup *)ale->data; agroup_to_keylist(adt, agrp, &anim_keys, NULL); } - else if (ale->type == ANIMTYPE_GPDATABLOCK) { - /* cleanup */ - // FIXME:... - BLI_freelistN(&anim_data); - return; - } else if (ale->type == ANIMTYPE_GPLAYER) { - struct bGPDlayer *gpl= (struct bGPDlayer *)ale->data; + // TODO: why don't we just give gplayers key_data too? + bGPDlayer *gpl = (bGPDlayer *)ale->data; gpl_to_keylist(ads, gpl, &anim_keys); } - /* loop through keyframes, finding one that was within the range clicked on */ - // TODO: replace this with API calls instead of inlining + /* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */ for (ak= anim_keys.root; ak; ak= akn) { if (IN_RANGE(ak->cfra, rectf.xmin, rectf.xmax)) { /* set the frame to use, and apply inverse-correction for NLA-mapping - * so that the frame will get selected by the selection functiosn without + * so that the frame will get selected by the selection functions without * requiring to map each frame once again... */ selx= BKE_nla_tweakedit_remap(adt, ak->cfra, NLATIME_CONVERT_UNMAP); @@ -1045,11 +1025,16 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, } } else if (ac->datatype == ANIMCONT_GPENCIL) { + /* deselect all other channels first */ ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); - /* Highlight gpencil layer */ - //gpl->flag |= GP_LAYER_SELECT; - //gpencil_layer_setactive(gpd, gpl); + /* Highlight GPencil Layer */ + if ((ale && ale->data) && (ale->type == ANIMTYPE_GPLAYER)) { + bGPDlayer *gpl = ale->data; + + gpl->flag |= GP_LAYER_SELECT; + //gpencil_layer_setactive(gpd, gpl); + } } } @@ -1057,11 +1042,7 @@ static void mouse_action_keys (bAnimContext *ac, int mval[2], short select_mode, if (ale) { if (found) { /* apply selection to keyframes */ - if (/*gpl*/0) { - /* grease pencil */ - //select_gpencil_frame(gpl, (int)selx, selectmode); - } - else if (column) { + if (column) { /* select all keyframes in the same frame as the one we hit on the active channel */ actkeys_mselect_column(ac, select_mode, selx); } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index faeb7a68968..792f212f638 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -351,6 +351,13 @@ static void action_listener(ScrArea *sa, wmNotifier *wmn) /* context changes */ switch (wmn->category) { + case NC_SCREEN: + if (wmn->data == ND_GPENCIL) { + /* only handle this event in GPencil mode for performance considerations */ + if (saction->mode == SACTCONT_GPENCIL) + ED_area_tag_redraw(sa); + } + break; case NC_ANIMATION: /* for selection changes of animation data, we can just redraw... otherwise autocolor might need to be done again */ if (ELEM(wmn->data, ND_KEYFRAME, ND_ANIMCHAN) && (wmn->action == NA_SELECTED)) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fce1247ec6f..8725e0ba5b9 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -47,6 +47,7 @@ #include "DNA_constraint_types.h" #include "DNA_scene_types.h" #include "DNA_meshdata_types.h" +#include "DNA_gpencil_types.h" #include "MEM_guardedalloc.h" @@ -57,6 +58,7 @@ #include "BKE_constraint.h" #include "BKE_depsgraph.h" #include "BKE_fcurve.h" +#include "BKE_gpencil.h" #include "BKE_global.h" #include "BKE_key.h" #include "BKE_main.h" @@ -2804,7 +2806,6 @@ static void createTransNlaData(bContext *C, TransInfo *t) * It also makes sure gp-frames are still stored in chronological order after * transform. */ -#if 0 static void posttrans_gpd_clean (bGPdata *gpd) { bGPDlayer *gpl; @@ -2813,17 +2814,17 @@ static void posttrans_gpd_clean (bGPdata *gpd) ListBase sel_buffer = {NULL, NULL}; bGPDframe *gpf, *gpfn; bGPDframe *gfs, *gfsn; - + /* loop 1: loop through and isolate selected gp-frames to buffer * (these need to be sorted as they are isolated) */ for (gpf= gpl->frames.first; gpf; gpf= gpfn) { short added= 0; gpfn= gpf->next; - + if (gpf->flag & GP_FRAME_SELECT) { BLI_remlink(&gpl->frames, gpf); - + /* find place to add them in buffer * - go backwards as most frames will still be in order, * so doing it this way will be faster @@ -2840,27 +2841,27 @@ static void posttrans_gpd_clean (bGPdata *gpd) BLI_addhead(&sel_buffer, gpf); } } - + /* error checking: it is unlikely, but may be possible to have none selected */ if (sel_buffer.first == NULL) continue; - + /* if all were selected (i.e. gpl->frames is empty), then just transfer sel-buf over */ if (gpl->frames.first == NULL) { gpl->frames.first= sel_buffer.first; gpl->frames.last= sel_buffer.last; - + continue; } - + /* loop 2: remove duplicates of frames in buffers */ for (gpf= gpl->frames.first; gpf && sel_buffer.first; gpf= gpfn) { gpfn= gpf->next; - + /* loop through sel_buffer, emptying stuff from front of buffer if ok */ for (gfs= sel_buffer.first; gfs && gpf; gfs= gfsn) { gfsn= gfs->next; - + /* if this buffer frame needs to go before current, add it! */ if (gfs->framenum < gpf->framenum) { /* transfer buffer frame to frames list (before current) */ @@ -2872,24 +2873,22 @@ static void posttrans_gpd_clean (bGPdata *gpd) /* transfer buffer frame to frames list (before current) */ BLI_remlink(&sel_buffer, gfs); BLI_insertlinkbefore(&gpl->frames, gpf, gfs); - + /* get rid of current frame */ - // TRANSFORM_FIX_ME - //gpencil_layer_delframe(gpl, gpf); + gpencil_layer_delframe(gpl, gpf); } } } - + /* if anything is still in buffer, append to end */ for (gfs= sel_buffer.first; gfs; gfs= gfsn) { gfsn= gfs->next; - + BLI_remlink(&sel_buffer, gfs); BLI_addtail(&gpl->frames, gfs); } } } -#endif /* Called during special_aftertrans_update to make sure selected keyframes replace * any other keyframes which may reside on that frame (that is not selected). @@ -3012,15 +3011,14 @@ static int count_fcurve_keys(FCurve *fcu, char side, float cfra) } /* fully select selected beztriples, but only include if it's on the right side of cfra */ -#if 0 static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) { bGPDframe *gpf; int count = 0; - + if (gpl == NULL) return count; - + /* only include points that occur on the right side of cfra */ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { if (gpf->flag & GP_FRAME_SELECT) { @@ -3028,10 +3026,9 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra) count++; } } - + return count; } -#endif /* This function assigns the information to transdata */ static void TimeToTransData(TransData *td, float *time, AnimData *adt) @@ -3068,23 +3065,23 @@ static TransData *ActionFCurveToTransData(TransData *td, TransData2D **td2dv, FC /* only add if on the right 'side' of the current frame */ if (FrameOnMouseSide(side, bezt->vec[1][0], cfra)) { TimeToTransData(td, bezt->vec[1], adt); - + /*set flags to move handles as necassary*/ td->flag |= TD_MOVEHANDLE1|TD_MOVEHANDLE2; td2d->h1 = bezt->vec[0]; td2d->h2 = bezt->vec[2]; - + VECCOPY2D(td2d->ih1, td2d->h1); VECCOPY2D(td2d->ih2, td2d->h2); - + td++; td2d++; } } } - + *td2dv = td2d; - + return td; } @@ -3119,12 +3116,11 @@ void flushTransGPactionData (TransInfo *t) * The 'side' argument is needed for the extend mode. 'B' = both sides, 'R'/'L' mean only data * on the named side are used. */ -#if 0 static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl, char side, float cfra) { bGPDframe *gpf; int count= 0; - + /* check for select frames on right side of current frame */ for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { if (gpf->flag & GP_FRAME_SELECT) { @@ -3132,10 +3128,10 @@ static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl /* memory is calloc'ed, so that should zero everything nicely for us */ td->val= &tfd->val; td->ival= (float)gpf->framenum; - + tfd->val= (float)gpf->framenum; tfd->sdata= &gpf->framenum; - + /* advance td now */ td++; tfd++; @@ -3143,10 +3139,9 @@ static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl } } } - + return count; } -#endif static void createTransActionData(bContext *C, TransInfo *t) { @@ -3199,10 +3194,10 @@ static void createTransActionData(bContext *C, TransInfo *t) else cfra = (float)CFRA; - //if (ale->type == ANIMTYPE_GPLAYER) - // count += count_gplayer_frames(ale->data, t->frame_side, cfra); - //else + if (ale->type == ANIMTYPE_FCURVE) count += count_fcurve_keys(ale->key_data, t->frame_side, cfra); + else + count += count_gplayer_frames(ale->data, t->frame_side, cfra); } /* stop if trying to build list if nothing selected */ @@ -3235,15 +3230,15 @@ static void createTransActionData(bContext *C, TransInfo *t) /* loop 2: build transdata array */ for (ale= anim_data.first; ale; ale= ale->next) { - //if (ale->type == ANIMTYPE_GPLAYER) { - // bGPDlayer *gpl= (bGPDlayer *)ale->data; - // int i; - // - // i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra); - // td += i; - // tfd += i; - //} - //else { + if (ale->type == ANIMTYPE_GPLAYER) { + bGPDlayer *gpl= (bGPDlayer *)ale->data; + int i; + + i = GPLayerToTransData(td, tfd, gpl, t->frame_side, cfra); + td += i; + tfd += i; + } + else { AnimData *adt= ANIM_nla_mapping_get(&ac, ale); FCurve *fcu= (FCurve *)ale->key_data; @@ -3256,7 +3251,7 @@ static void createTransActionData(bContext *C, TransInfo *t) cfra = (float)CFRA; td= ActionFCurveToTransData(td, &td2d, fcu, adt, t->frame_side, cfra); - //} + } } /* check if we're supposed to be setting minx/maxx for TimeSlide */ @@ -4916,27 +4911,21 @@ void special_aftertrans_update(bContext *C, TransInfo *t) scene_marker_tfm_scale(t->scene, t->vec[0], SELECT); } } - -#if 0 // XXX future of this is still not clear + else if (ac.datatype == ANIMCONT_GPENCIL) { /* remove duplicate frames and also make sure points are in order! */ if ((cancelled == 0) || (duplicate)) { - bScreen *sc= (bScreen *)ac.data; - ScrArea *sa; + bGPdata *gpd; - /* BAD... we need to loop over all screen areas for current screen... - * - sync this with actdata_filter_gpencil() in editaction.c - */ - for (sa= sc->areabase.first; sa; sa= sa->next) { - bGPdata *gpd= gpencil_data_get_active(sa); - - if (gpd) + // XXX: BAD! this get gpencil datablocks directly from main db... + // but that's how this currently works :/ + for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) { + if (ID_REAL_USERS(gpd) > 1) posttrans_gpd_clean(gpd); } } } -#endif // XXX future of this is still not clear /* make sure all F-Curves are set correctly */ ANIM_editkeyframes_refresh(&ac); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index dbf984b6659..839e813f1ae 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -349,22 +349,29 @@ void recalcData(TransInfo *t) ANIM_animdata_context_getdata(&ac); - /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ - filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); - - /* just tag these animdata-blocks to recalc, assuming that some data there changed - * BUT only do this if realtime updates are enabled - */ - if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) { - for (ale= anim_data.first; ale; ale= ale->next) { - /* set refresh tags for objects using this animation */ - ANIM_list_elem_update(t->scene, ale); - } + /* perform flush */ + if (ac.datatype == ANIMCONT_GPENCIL) { + /* flush transform values back to actual coordinates */ + flushTransGPactionData(t); + } + else { + /* get animdata blocks visible in editor, assuming that these will be the ones where things changed */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA); + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + /* just tag these animdata-blocks to recalc, assuming that some data there changed + * BUT only do this if realtime updates are enabled + */ + if ((saction->flag & SACTION_NOREALTIMEUPDATES) == 0) { + for (ale= anim_data.first; ale; ale= ale->next) { + /* set refresh tags for objects using this animation */ + ANIM_list_elem_update(t->scene, ale); + } + } + + /* now free temp channels */ + BLI_freelistN(&anim_data); } - - /* now free temp channels */ - BLI_freelistN(&anim_data); } else if (t->spacetype == SPACE_IPO) { Scene *scene; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 54b34c6ba45..327bbd25db2 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -1692,7 +1692,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) {SACTCONT_DOPESHEET, "DOPESHEET", 0, "DopeSheet", ""}, {SACTCONT_ACTION, "ACTION", 0, "Action Editor", ""}, {SACTCONT_SHAPEKEY, "SHAPEKEY", 0, "ShapeKey Editor", ""}, - //{SACTCONT_GPENCIL, "GPENCIL", 0, "Grease Pencil", ""}, // XXX: to be reimplemented, but not enough time before 2.53 - Aligorith, 2010Jul14 + {SACTCONT_GPENCIL, "GPENCIL", 0, "Grease Pencil", ""}, {0, NULL, 0, NULL, NULL}};