diff options
author | Joshua Leung <aligorith@gmail.com> | 2011-01-11 01:10:28 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2011-01-11 01:10:28 +0300 |
commit | cf25b10eb5bb61662ce0db6b3ef54a3e3e73a328 (patch) | |
tree | 0d7ffcdd0735d1788bfb3e679b6f7489605c1aab | |
parent | d841a206314922eec0a0fed0b87e3078b68487c9 (diff) |
Todo #22395: Restoring Grease Pencil Editing Mode in DopeSheet Editor
This commit restores some basic functionality for retiming Grease
Pencil sketches. Some of the functionality that existed before still
hasn't been restored (namely snap/mirror tools as well as copy+paste),
though it should be possible to use this for basic retiming and
sketch-frame management again.
- There's still a lot of work required to get this up to the standard
of the rest of the animation editor code, as some of this code was
originally just hacked in based on the old-style code.
- Work is already required to not have to directly access the main db
global to get the list of Grease Pencil datablocks to show, but that
can come along with pending cleanups of the filtering code.
-rw-r--r-- | release/scripts/ui/space_dopesheet.py | 80 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_channels_defines.c | 259 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_channels_edit.c | 50 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 44 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_draw.c | 70 | ||||
-rw-r--r-- | source/blender/editors/gpencil/editaction_gpencil.c | 55 | ||||
-rw-r--r-- | source/blender/editors/include/ED_gpencil.h | 23 | ||||
-rw-r--r-- | source/blender/editors/space_action/SConscript | 2 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit.c | 12 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_select.c | 119 | ||||
-rw-r--r-- | source/blender/editors/space_action/space_action.c | 7 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 103 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 35 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_space.c | 2 |
14 files changed, 501 insertions, 360 deletions
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... - - indent = 0; - group= 3; + /* 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; - /* 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; - } + default: + return 0; + } +} + +/* 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; - 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:<None>"); - - special= ICON_IMAGE_COL; - } - break; - - default: - { - sprintf(name, "<Unknown GP-Data Source>"); - special= -1; - } - break; - } - } - break; - case ANIMTYPE_GPLAYER: /* gpencil layer */ - { - bGPDlayer *gpl = (bGPDlayer *)ale->data; + 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; - indent = 0; - special = -1; - expand = -1; - group = 1; + case ACHANNEL_SETTING_MUTE: /* muted */ + return GP_LAYER_HIDE; - 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; + case ACHANNEL_SETTING_PROTECT: /* protected */ + //*neg= 1; - if we change this to edtiability + return GP_LAYER_LOCKED; - 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: /* unsupported */ + return 0; } } -#endif + +/* 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; - } - else if (x >= (ACHANNEL_NAMEWIDTH-32)) { - /* toggle hide */ - gpl->flag ^= GP_LAYER_HIDE; + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* invert selection status of this layer only */ + 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); - //} + else { + /* select layer by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + gpl->flag |= GP_LAYER_SELECT; } -#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,20 +31,23 @@ #include <stddef.h> #include <math.h> -#include "BLI_math.h" +#include "MEM_guardedalloc.h" + #include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" -#include "gpencil_intern.h" +#include "DNA_gpencil_types.h" +#include "DNA_scene_types.h" -#if 0 // XXX disabled until grease pencil code stabilises again +#include "BKE_fcurve.h" +#include "BKE_gpencil.h" -/* 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 */ +#include "ED_anim_api.h" +#include "ED_gpencil.h" +#include "ED_keyframes_edit.h" +#include "gpencil_intern.h" /* ***************************************** */ /* NOTE ABOUT THIS FILE: @@ -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}}; |