forked from bartvdbraak/blender
mask animation keys now editable in the dope sheet (duplicate, transform, delete, select- etc).
This commit is contained in:
parent
68c365e2f0
commit
b33c5168f4
@ -151,6 +151,7 @@ int BKE_mask_layer_shape_find_frame_range(struct MaskLayer *masklay, const float
|
|||||||
struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame);
|
struct MaskLayerShape *BKE_mask_layer_shape_alloc(struct MaskLayer *masklay, const int frame);
|
||||||
void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape);
|
void BKE_mask_layer_shape_free(struct MaskLayerShape *masklay_shape);
|
||||||
struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, const int frame);
|
struct MaskLayerShape *BKE_mask_layer_shape_varify_frame(struct MaskLayer *masklay, const int frame);
|
||||||
|
struct MaskLayerShape *BKE_mask_layer_shape_duplicate(struct MaskLayerShape *masklay_shape);
|
||||||
void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape);
|
void BKE_mask_layer_shape_unlink(struct MaskLayer *masklay, struct MaskLayerShape *masklay_shape);
|
||||||
void BKE_mask_layer_shape_sort(struct MaskLayer *masklay);
|
void BKE_mask_layer_shape_sort(struct MaskLayer *masklay);
|
||||||
|
|
||||||
|
@ -1820,6 +1820,19 @@ MaskLayerShape *BKE_mask_layer_shape_varify_frame(MaskLayer *masklay, const int
|
|||||||
return masklay_shape;
|
return masklay_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaskLayerShape *BKE_mask_layer_shape_duplicate(MaskLayerShape *masklay_shape)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape_copy;
|
||||||
|
|
||||||
|
masklay_shape_copy = MEM_dupallocN(masklay_shape);
|
||||||
|
|
||||||
|
if (LIKELY(masklay_shape_copy->data)) {
|
||||||
|
masklay_shape_copy->data = MEM_dupallocN(masklay_shape_copy->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return masklay_shape_copy;
|
||||||
|
}
|
||||||
|
|
||||||
void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape)
|
void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape)
|
||||||
{
|
{
|
||||||
BLI_remlink(&masklay->splines_shapes, masklay_shape);
|
BLI_remlink(&masklay->splines_shapes, masklay_shape);
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include "DNA_world_types.h"
|
#include "DNA_world_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
#include "DNA_speaker_types.h"
|
#include "DNA_speaker_types.h"
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
|
|
||||||
@ -2516,6 +2517,172 @@ static bAnimChannelType ACF_GPL =
|
|||||||
acf_gpl_setting_ptr /* pointer for setting */
|
acf_gpl_setting_ptr /* pointer for setting */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Mask Datablock ------------------------------------------- */
|
||||||
|
|
||||||
|
/* get backdrop color for mask datablock widget */
|
||||||
|
static void acf_mask_color(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), float r_color[3])
|
||||||
|
{
|
||||||
|
/* these are ID-blocks, but not exactly standalone... */
|
||||||
|
UI_GetThemeColorShade3fv(TH_DOPESHEET_CHANNELSUBOB, 20, r_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: just get this from RNA?
|
||||||
|
static int acf_mask_icon(bAnimListElem *UNUSED(ale))
|
||||||
|
{
|
||||||
|
return ICON_GREASEPENCIL; // MASK_TODO - need real icon
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if some setting exists for this channel */
|
||||||
|
static short acf_mask_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
|
||||||
|
{
|
||||||
|
switch (setting) {
|
||||||
|
/* only select and expand supported */
|
||||||
|
case ACHANNEL_SETTING_SELECT:
|
||||||
|
case ACHANNEL_SETTING_EXPAND:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the appropriate flag(s) for the setting when it is valid */
|
||||||
|
static int acf_mask_setting_flag(bAnimContext *UNUSED(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 MASK_ANIMF_EXPAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this shouldn't happen */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get pointer to the setting */
|
||||||
|
static void *acf_mask_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type)
|
||||||
|
{
|
||||||
|
Mask *mask = (Mask *)ale->data;
|
||||||
|
|
||||||
|
/* all flags are just in mask->flag for now... */
|
||||||
|
return GET_ACF_FLAG_PTR(mask->flag, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mask datablock type define */
|
||||||
|
static bAnimChannelType ACF_MASKDATA =
|
||||||
|
{
|
||||||
|
"Mask Datablock", /* type name */
|
||||||
|
|
||||||
|
acf_mask_color, /* backdrop color */
|
||||||
|
acf_group_backdrop, /* backdrop */
|
||||||
|
acf_generic_indention_0, /* indent level */
|
||||||
|
acf_generic_group_offset, /* offset */
|
||||||
|
|
||||||
|
acf_generic_idblock_name, /* name */
|
||||||
|
acf_generic_idfill_nameprop, /* name prop */
|
||||||
|
acf_mask_icon, /* icon */
|
||||||
|
|
||||||
|
acf_mask_setting_valid, /* has setting */
|
||||||
|
acf_mask_setting_flag, /* flag for setting */
|
||||||
|
acf_mask_setting_ptr /* pointer for setting */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Mask Layer ------------------------------------------- */
|
||||||
|
|
||||||
|
/* name for grease pencil layer entries */
|
||||||
|
static void acf_masklay_name(bAnimListElem *ale, char *name)
|
||||||
|
{
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
|
||||||
|
if (masklay && name)
|
||||||
|
BLI_strncpy(name, masklay->name, ANIM_CHAN_NAME_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* name property for grease pencil layer entries */
|
||||||
|
static short acf_masklay_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
|
||||||
|
{
|
||||||
|
if (ale->data) {
|
||||||
|
RNA_pointer_create(ale->id, &RNA_MaskLayer, ale->data, ptr);
|
||||||
|
*prop = RNA_struct_name_property(ptr->type);
|
||||||
|
|
||||||
|
return (*prop != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if some setting exists for this channel */
|
||||||
|
static short acf_masklay_setting_valid(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale), int setting)
|
||||||
|
{
|
||||||
|
switch (setting) {
|
||||||
|
/* unsupported */
|
||||||
|
case ACHANNEL_SETTING_EXPAND: /* mask 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_masklay_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
|
||||||
|
{
|
||||||
|
/* clear extra return data first */
|
||||||
|
*neg = 0;
|
||||||
|
|
||||||
|
switch (setting) {
|
||||||
|
case ACHANNEL_SETTING_SELECT: /* selected */
|
||||||
|
return MASK_LAYERFLAG_SELECT;
|
||||||
|
|
||||||
|
// case ACHANNEL_SETTING_MUTE: /* muted */
|
||||||
|
// return GP_LAYER_HIDE;
|
||||||
|
|
||||||
|
case ACHANNEL_SETTING_PROTECT: /* protected */
|
||||||
|
// *neg = 1; - if we change this to edtiability
|
||||||
|
return MASK_LAYERFLAG_LOCKED;
|
||||||
|
|
||||||
|
default: /* unsupported */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get pointer to the setting */
|
||||||
|
static void *acf_masklay_setting_ptr(bAnimListElem *ale, int UNUSED(setting), short *type)
|
||||||
|
{
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
|
||||||
|
/* all flags are just in agrp->flag for now... */
|
||||||
|
return GET_ACF_FLAG_PTR(masklay->flag, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* grease pencil layer type define */
|
||||||
|
static bAnimChannelType ACF_MASKLAYER =
|
||||||
|
{
|
||||||
|
"Mask 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_masklay_name, /* name */
|
||||||
|
acf_masklay_name_prop, /* name prop */
|
||||||
|
NULL, /* icon */
|
||||||
|
|
||||||
|
acf_masklay_setting_valid, /* has setting */
|
||||||
|
acf_masklay_setting_flag, /* flag for setting */
|
||||||
|
acf_masklay_setting_ptr /* pointer for setting */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* *********************************************** */
|
/* *********************************************** */
|
||||||
/* Type Registration and General Access */
|
/* Type Registration and General Access */
|
||||||
|
|
||||||
@ -2566,6 +2733,9 @@ static void ANIM_init_channel_typeinfo_data(void)
|
|||||||
animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */
|
animchannelTypeInfo[type++] = &ACF_GPD; /* Grease Pencil Datablock */
|
||||||
animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */
|
animchannelTypeInfo[type++] = &ACF_GPL; /* Grease Pencil Layer */
|
||||||
|
|
||||||
|
animchannelTypeInfo[type++] = &ACF_MASKDATA; /* Mask Datablock */
|
||||||
|
animchannelTypeInfo[type++] = &ACF_MASKLAYER; /* Mask Layer */
|
||||||
|
|
||||||
// TODO: these types still need to be implemented!!!
|
// TODO: these types still need to be implemented!!!
|
||||||
// probably need a few extra flags for these special cases...
|
// probably need a few extra flags for these special cases...
|
||||||
animchannelTypeInfo[type++] = NULL; /* NLA Track */
|
animchannelTypeInfo[type++] = NULL; /* NLA Track */
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
#include "RNA_define.h"
|
#include "RNA_define.h"
|
||||||
@ -51,6 +52,7 @@
|
|||||||
#include "BKE_fcurve.h"
|
#include "BKE_fcurve.h"
|
||||||
#include "BKE_gpencil.h"
|
#include "BKE_gpencil.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
|
#include "BKE_mask.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
|
|
||||||
#include "UI_view2d.h"
|
#include "UI_view2d.h"
|
||||||
@ -258,6 +260,10 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
|
|||||||
if (ale->flag & GP_LAYER_SELECT)
|
if (ale->flag & GP_LAYER_SELECT)
|
||||||
sel = ACHANNEL_SETFLAG_CLEAR;
|
sel = ACHANNEL_SETFLAG_CLEAR;
|
||||||
break;
|
break;
|
||||||
|
case ANIMTYPE_MASKLAYER:
|
||||||
|
if (ale->flag & MASK_LAYERFLAG_SELECT)
|
||||||
|
sel = ACHANNEL_SETFLAG_CLEAR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,6 +360,14 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, short datatype, s
|
|||||||
ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT);
|
ACHANNEL_SET_FLAG(gpl, sel, GP_LAYER_SELECT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ANIMTYPE_MASKLAYER:
|
||||||
|
{
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
|
||||||
|
ACHANNEL_SET_FLAG(masklay, sel, MASK_LAYERFLAG_SELECT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,6 +1069,10 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
|
|||||||
/* Grease Pencil channels */
|
/* Grease Pencil channels */
|
||||||
printf("Grease Pencil not supported for moving yet\n");
|
printf("Grease Pencil not supported for moving yet\n");
|
||||||
}
|
}
|
||||||
|
else if (ac.datatype == ANIMCONT_MASK) {
|
||||||
|
/* Grease Pencil channels */
|
||||||
|
printf("Mask does not supported for moving yet\n");
|
||||||
|
}
|
||||||
else if (ac.datatype == ANIMCONT_ACTION) {
|
else if (ac.datatype == ANIMCONT_ACTION) {
|
||||||
/* Directly rearrange action's channels */
|
/* Directly rearrange action's channels */
|
||||||
rearrange_action_channels(&ac, ac.data, mode);
|
rearrange_action_channels(&ac, ac.data, mode);
|
||||||
@ -1205,6 +1223,17 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
BLI_freelinkN(&gpd->layers, gpl);
|
BLI_freelinkN(&gpd->layers, gpl);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ANIMTYPE_MASKLAYER:
|
||||||
|
{
|
||||||
|
/* Grease Pencil layer */
|
||||||
|
Mask *mask = (Mask *)ale->id;
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
|
||||||
|
/* try to delete the layer's data and the layer itself */
|
||||||
|
BKE_mask_layer_remove(mask, masklay);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2287,6 +2316,36 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in
|
|||||||
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
|
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ANIMTYPE_MASKDATABLOCK:
|
||||||
|
{
|
||||||
|
Mask *mask = (Mask *)ale->data;
|
||||||
|
|
||||||
|
/* toggle expand
|
||||||
|
* - although the triangle widget already allows this, the whole channel can also be used for this purpose
|
||||||
|
*/
|
||||||
|
mask->flag ^= MASK_ANIMF_EXPAND;
|
||||||
|
|
||||||
|
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANIMTYPE_MASKLAYER:
|
||||||
|
{
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
|
||||||
|
/* select/deselect */
|
||||||
|
if (selectmode == SELECT_INVERT) {
|
||||||
|
/* invert selection status of this layer only */
|
||||||
|
masklay->flag ^= MASK_LAYERFLAG_SELECT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* select layer by itself */
|
||||||
|
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
|
||||||
|
masklay->flag |= MASK_LAYERFLAG_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (G.debug & G_DEBUG)
|
if (G.debug & G_DEBUG)
|
||||||
printf("Error: Invalid channel type in mouse_anim_channels()\n");
|
printf("Error: Invalid channel type in mouse_anim_channels()\n");
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include "DNA_lamp_types.h"
|
#include "DNA_lamp_types.h"
|
||||||
#include "DNA_lattice_types.h"
|
#include "DNA_lattice_types.h"
|
||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
#include "DNA_meta_types.h"
|
#include "DNA_meta_types.h"
|
||||||
@ -86,6 +87,7 @@
|
|||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
#include "BKE_node.h"
|
#include "BKE_node.h"
|
||||||
|
#include "BKE_mask.h"
|
||||||
#include "BKE_sequencer.h"
|
#include "BKE_sequencer.h"
|
||||||
#include "BKE_utildefines.h"
|
#include "BKE_utildefines.h"
|
||||||
|
|
||||||
@ -173,6 +175,22 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction)
|
|||||||
ac->mode = saction->mode;
|
ac->mode = saction->mode;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
case SACTCONT_MASK: /* Grease Pencil */ // XXX review how this mode is handled...
|
||||||
|
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
|
||||||
|
{
|
||||||
|
// TODO, other methods to get the mask
|
||||||
|
// Sequence *seq = BKE_sequencer_active_get(ac->scene);
|
||||||
|
//MovieClip *clip = ac->scene->clip;
|
||||||
|
// struct Mask *mask = seq ? seq->mask : NULL;
|
||||||
|
|
||||||
|
saction->ads.source = (ID *)ac->scene;;
|
||||||
|
|
||||||
|
ac->datatype = ANIMCONT_MASK;
|
||||||
|
ac->data = &saction->ads;
|
||||||
|
|
||||||
|
ac->mode = saction->mode;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
case SACTCONT_DOPESHEET: /* DopeSheet */
|
case SACTCONT_DOPESHEET: /* DopeSheet */
|
||||||
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
|
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
|
||||||
saction->ads.source = (ID *)ac->scene;
|
saction->ads.source = (ID *)ac->scene;
|
||||||
@ -808,6 +826,17 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ANIMTYPE_MASKLAYER:
|
||||||
|
{
|
||||||
|
MaskLayer *masklay = (MaskLayer *)data;
|
||||||
|
|
||||||
|
ale->flag = masklay->flag;
|
||||||
|
|
||||||
|
ale->key_data = NULL;
|
||||||
|
ale->datatype = ALE_MASKLAY;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ANIMTYPE_NLATRACK:
|
case ANIMTYPE_NLATRACK:
|
||||||
{
|
{
|
||||||
NlaTrack *nlt = (NlaTrack *)data;
|
NlaTrack *nlt = (NlaTrack *)data;
|
||||||
@ -1353,6 +1382,83 @@ static size_t animdata_filter_gpencil(ListBase *anim_data, void *UNUSED(data), i
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
|
||||||
|
{
|
||||||
|
MaskLayer *masklay_act = BKE_mask_layer_active(mask);
|
||||||
|
MaskLayer *masklay;
|
||||||
|
size_t items = 0;
|
||||||
|
|
||||||
|
/* loop over layers as the conditions are acceptable */
|
||||||
|
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
|
||||||
|
/* only if selected */
|
||||||
|
if (ANIMCHANNEL_SELOK(SEL_MASKLAY(masklay)) ) {
|
||||||
|
/* only if editable */
|
||||||
|
// if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
|
||||||
|
/* active... */
|
||||||
|
if (!(filter_mode & ANIMFILTER_ACTIVE) || (masklay_act == masklay)) {
|
||||||
|
/* add to list */
|
||||||
|
ANIMCHANNEL_NEW_CHANNEL(masklay, ANIMTYPE_MASKLAYER, mask);
|
||||||
|
|
||||||
|
|
||||||
|
// if (filter_mode & ANIMFILTER_TMP_PEEK)
|
||||||
|
// return 1;
|
||||||
|
// else {
|
||||||
|
// bAnimListElem *ale = make_new_animlistelem(masklay, channel_type, (ID *)owner_id);
|
||||||
|
// if (ale) {
|
||||||
|
// BLI_addtail(anim_data, ale);
|
||||||
|
// items ++;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t animdata_filter_mask(ListBase *anim_data, void *UNUSED(data), int filter_mode)
|
||||||
|
{
|
||||||
|
Mask *mask;
|
||||||
|
size_t items = 0;
|
||||||
|
|
||||||
|
/* for now, grab grease pencil datablocks directly from main */
|
||||||
|
// XXX: this is not good...
|
||||||
|
for (mask = G.main->mask.first; mask; mask = mask->id.next) {
|
||||||
|
ListBase tmp_data = {NULL, NULL};
|
||||||
|
size_t tmp_items = 0;
|
||||||
|
|
||||||
|
/* only show if gpd is used by something... */
|
||||||
|
if (ID_REAL_USERS(mask) < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* add gpencil animation channels */
|
||||||
|
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_MASK(mask))
|
||||||
|
{
|
||||||
|
tmp_items += animdata_filter_mask_data(&tmp_data, mask, filter_mode);
|
||||||
|
}
|
||||||
|
END_ANIMFILTER_SUBCHANNELS;
|
||||||
|
|
||||||
|
/* did we find anything? */
|
||||||
|
if (tmp_items) {
|
||||||
|
/* include data-expand widget first */
|
||||||
|
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
|
||||||
|
/* add gpd as channel too (if for drawing, and it has layers) */
|
||||||
|
ANIMCHANNEL_NEW_CHANNEL(mask, ANIMTYPE_MASKDATABLOCK, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now add the list of collected channels */
|
||||||
|
BLI_movelisttolist(anim_data, &tmp_data);
|
||||||
|
BLI_assert((tmp_data.first == tmp_data.last) && (tmp_data.first == NULL));
|
||||||
|
items += tmp_items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the number of items added to the list */
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
/* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */
|
/* NOTE: owner_id is scene, material, or texture block, which is the direct owner of the node tree in question */
|
||||||
// TODO: how to handle group nodes is still unclear...
|
// TODO: how to handle group nodes is still unclear...
|
||||||
static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
|
static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, bNodeTree *ntree, int filter_mode)
|
||||||
@ -2295,6 +2401,12 @@ size_t ANIM_animdata_filter(bAnimContext *ac, ListBase *anim_data, int filter_mo
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ANIMCONT_MASK:
|
||||||
|
{
|
||||||
|
items = animdata_filter_mask(anim_data, data, filter_mode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
|
case ANIMCONT_DOPESHEET: /* 'DopeSheet Editor' */
|
||||||
{
|
{
|
||||||
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
|
/* the DopeSheet editor is the primary place where the DopeSheet summaries are useful */
|
||||||
|
@ -209,7 +209,7 @@ static DLRBT_Node *nalloc_ak_masklayshape(void *data)
|
|||||||
|
|
||||||
/* store settings based on state of BezTriple */
|
/* store settings based on state of BezTriple */
|
||||||
ak->cfra = masklay_shape->frame;
|
ak->cfra = masklay_shape->frame;
|
||||||
ak->sel = (masklay_shape->flag & SELECT) ? SELECT : 0;
|
ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
|
||||||
|
|
||||||
/* set 'modified', since this is used to identify long keyframes */
|
/* set 'modified', since this is used to identify long keyframes */
|
||||||
ak->modified = 1;
|
ak->modified = 1;
|
||||||
@ -224,7 +224,7 @@ static void nupdate_ak_masklayshape(void *node, void *data)
|
|||||||
MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
|
MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
|
||||||
|
|
||||||
/* set selection status and 'touched' status */
|
/* set selection status and 'touched' status */
|
||||||
if (masklay_shape->flag & SELECT) ak->sel = SELECT;
|
if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT;
|
||||||
ak->modified += 1;
|
ak->modified += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,6 +818,21 @@ void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
|
|||||||
BLI_dlrbTree_free(&keys);
|
BLI_dlrbTree_free(&keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos)
|
||||||
|
{
|
||||||
|
DLRBT_Tree keys;
|
||||||
|
|
||||||
|
BLI_dlrbTree_init(&keys);
|
||||||
|
|
||||||
|
mask_to_keylist(ads, masklay, &keys);
|
||||||
|
|
||||||
|
BLI_dlrbTree_linkedlist_sync(&keys);
|
||||||
|
|
||||||
|
draw_keylist(v2d, &keys, NULL, ypos, (masklay->flag & MASK_LAYERFLAG_LOCKED));
|
||||||
|
|
||||||
|
BLI_dlrbTree_free(&keys);
|
||||||
|
}
|
||||||
|
|
||||||
/* *************************** Keyframe List Conversions *************************** */
|
/* *************************** Keyframe List Conversions *************************** */
|
||||||
|
|
||||||
void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
|
void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
|
||||||
|
@ -97,7 +97,8 @@ typedef enum eAnimCont_Types {
|
|||||||
ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */
|
ANIMCONT_FCURVES = 5, /* animation F-Curves (bDopesheet) */
|
||||||
ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */
|
ANIMCONT_DRIVERS = 6, /* drivers (bDopesheet) */
|
||||||
ANIMCONT_NLA = 7, /* nla (bDopesheet) */
|
ANIMCONT_NLA = 7, /* nla (bDopesheet) */
|
||||||
ANIMCONT_CHANNEL = 8 /* animation channel (bAnimListElem) */
|
ANIMCONT_CHANNEL = 8, /* animation channel (bAnimListElem) */
|
||||||
|
ANIMCONT_MASK = 9 /* mask dopesheet */
|
||||||
} eAnimCont_Types;
|
} eAnimCont_Types;
|
||||||
|
|
||||||
/* --------------- Channels -------------------- */
|
/* --------------- Channels -------------------- */
|
||||||
@ -161,6 +162,9 @@ typedef enum eAnim_ChannelType {
|
|||||||
ANIMTYPE_GPDATABLOCK,
|
ANIMTYPE_GPDATABLOCK,
|
||||||
ANIMTYPE_GPLAYER,
|
ANIMTYPE_GPLAYER,
|
||||||
|
|
||||||
|
ANIMTYPE_MASKDATABLOCK,
|
||||||
|
ANIMTYPE_MASKLAYER,
|
||||||
|
|
||||||
ANIMTYPE_NLATRACK,
|
ANIMTYPE_NLATRACK,
|
||||||
ANIMTYPE_NLAACTION,
|
ANIMTYPE_NLAACTION,
|
||||||
|
|
||||||
@ -173,6 +177,7 @@ typedef enum eAnim_KeyType {
|
|||||||
ALE_NONE = 0, /* no keyframe data */
|
ALE_NONE = 0, /* no keyframe data */
|
||||||
ALE_FCURVE, /* F-Curve */
|
ALE_FCURVE, /* F-Curve */
|
||||||
ALE_GPFRAME, /* Grease Pencil Frames */
|
ALE_GPFRAME, /* Grease Pencil Frames */
|
||||||
|
ALE_MASKLAY, /* Mask */
|
||||||
ALE_NLASTRIP, /* NLA Strips */
|
ALE_NLASTRIP, /* NLA Strips */
|
||||||
|
|
||||||
ALE_ALL, /* All channels summary */
|
ALE_ALL, /* All channels summary */
|
||||||
@ -279,6 +284,15 @@ typedef enum eAnimFilter_Flags {
|
|||||||
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0)
|
#define EDITABLE_GPL(gpl) ((gpl->flag & GP_LAYER_LOCKED) == 0)
|
||||||
#define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT)
|
#define SEL_GPL(gpl) (gpl->flag & GP_LAYER_SELECT)
|
||||||
|
|
||||||
|
/* Mask Only */
|
||||||
|
/* Grease Pencil datablock settings */
|
||||||
|
#define EXPANDED_MASK(mask) (mask->flag & MASK_ANIMF_EXPAND)
|
||||||
|
/* Grease Pencil Layer settings */
|
||||||
|
#define EDITABLE_MASK(masklay) ((masklay->flag & MASK_LAYERFLAG_LOCKED) == 0)
|
||||||
|
#define SEL_MASKLAY(masklay) (masklay->flag & SELECT)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* NLA only */
|
/* NLA only */
|
||||||
#define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
|
#define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED)
|
||||||
#define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0)
|
#define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0)
|
||||||
|
@ -83,7 +83,8 @@ void draw_gpencil_view3d(struct Scene *scene, struct View3D *v3d, struct ARegion
|
|||||||
void gpencil_panel_standard(const struct bContext *C, struct Panel *pa);
|
void gpencil_panel_standard(const struct bContext *C, struct Panel *pa);
|
||||||
|
|
||||||
/* ----------- Grease-Pencil AnimEdit API ------------------ */
|
/* ----------- Grease-Pencil AnimEdit API ------------------ */
|
||||||
short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene, short (*gpf_cb)(struct bGPDframe *, struct Scene *));
|
short gplayer_frames_looper(struct bGPDlayer *gpl, struct Scene *scene,
|
||||||
|
short (*gpf_cb)(struct bGPDframe *, struct Scene *));
|
||||||
void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel);
|
void gplayer_make_cfra_list(struct bGPDlayer *gpl, ListBase *elems, short onlysel);
|
||||||
|
|
||||||
short is_gplayer_frame_selected(struct bGPDlayer *gpl);
|
short is_gplayer_frame_selected(struct bGPDlayer *gpl);
|
||||||
|
@ -123,6 +123,8 @@ void draw_summary_channel(struct View2D *v2d, struct bAnimContext *ac, float ypo
|
|||||||
/* Grease Pencil Layer */
|
/* Grease Pencil Layer */
|
||||||
// XXX not restored
|
// XXX not restored
|
||||||
void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos);
|
void draw_gpl_channel(struct View2D *v2d, struct bDopeSheet *ads, struct bGPDlayer *gpl, float ypos);
|
||||||
|
/* Mask Layer */
|
||||||
|
void draw_masklay_channel(struct View2D *v2d, struct bDopeSheet *ads, struct MaskLayer *masklay, float ypos);
|
||||||
|
|
||||||
/* Keydata Generation --------------- */
|
/* Keydata Generation --------------- */
|
||||||
/* F-Curve */
|
/* F-Curve */
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
struct wmKeyConfig;
|
struct wmKeyConfig;
|
||||||
struct MaskLayer;
|
struct MaskLayer;
|
||||||
|
struct MaskLayerShape;
|
||||||
|
|
||||||
/* mask_editor.c */
|
/* mask_editor.c */
|
||||||
void ED_operatortypes_mask(void);
|
void ED_operatortypes_mask(void);
|
||||||
@ -47,4 +48,25 @@ void ED_mask_layer_shape_auto_key(struct MaskLayer *masklay, const int frame);
|
|||||||
int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame);
|
int ED_mask_layer_shape_auto_key_all(struct Mask *mask, const int frame);
|
||||||
int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame);
|
int ED_mask_layer_shape_auto_key_select(struct Mask *mask, const int frame);
|
||||||
|
|
||||||
#endif /* ED_TEXT_H */
|
/* ----------- Mask AnimEdit API ------------------ */
|
||||||
|
short masklayer_frames_looper(struct MaskLayer *masklay, struct Scene *scene,
|
||||||
|
short (*masklay_shape_cb)(struct MaskLayerShape *, struct Scene *));
|
||||||
|
void masklayer_make_cfra_list(struct MaskLayer *masklay, ListBase *elems, short onlysel);
|
||||||
|
|
||||||
|
short is_masklayer_frame_selected(struct MaskLayer *masklay);
|
||||||
|
void set_masklayer_frame_selection(struct MaskLayer *masklay, short mode);
|
||||||
|
void select_mask_frames(struct MaskLayer *masklay, short select_mode);
|
||||||
|
void select_mask_frame(struct MaskLayer *masklay, int selx, short select_mode);
|
||||||
|
void borderselect_masklayer_frames(struct MaskLayer *masklay, float min, float max, short select_mode);
|
||||||
|
|
||||||
|
void delete_masklayer_frames(struct MaskLayer *masklay);
|
||||||
|
void duplicate_masklayer_frames(struct MaskLayer *masklay);
|
||||||
|
|
||||||
|
//void free_gpcopybuf(void);
|
||||||
|
//void copy_gpdata(void);
|
||||||
|
//void paste_gpdata(void);
|
||||||
|
|
||||||
|
void snap_masklayer_frames(struct MaskLayer *masklay, short mode);
|
||||||
|
void mirror_masklayer_frames(struct MaskLayer *masklay, short mode);
|
||||||
|
|
||||||
|
#endif /* __ED_MASK_H__ */
|
||||||
|
@ -40,6 +40,7 @@ set(SRC
|
|||||||
mask_add.c
|
mask_add.c
|
||||||
mask_draw.c
|
mask_draw.c
|
||||||
mask_edit.c
|
mask_edit.c
|
||||||
|
mask_editaction.c
|
||||||
mask_ops.c
|
mask_ops.c
|
||||||
mask_relationships.c
|
mask_relationships.c
|
||||||
mask_select.c
|
mask_select.c
|
||||||
|
253
source/blender/editors/mask/mask_editaction.c
Normal file
253
source/blender/editors/mask/mask_editaction.c
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2008, Blender Foundation
|
||||||
|
* This is a new part of Blender
|
||||||
|
*
|
||||||
|
* Contributor(s): Joshua Leung
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/editors/mask/mask_editaction.c
|
||||||
|
* \ingroup edgpencil
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "BLI_blenlib.h"
|
||||||
|
#include "BLI_math.h"
|
||||||
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
|
#include "BKE_fcurve.h"
|
||||||
|
#include "BKE_mask.h"
|
||||||
|
|
||||||
|
#include "ED_anim_api.h"
|
||||||
|
#include "ED_keyframes_edit.h"
|
||||||
|
|
||||||
|
/* ***************************************** */
|
||||||
|
/* NOTE ABOUT THIS FILE:
|
||||||
|
* This file contains code for editing Grease Pencil data in the Action Editor
|
||||||
|
* as a 'keyframes', so that a user can adjust the timing of Grease Pencil drawings.
|
||||||
|
* Therefore, this file mostly contains functions for selecting Grease-Pencil frames.
|
||||||
|
*/
|
||||||
|
/* ***************************************** */
|
||||||
|
/* Generics - Loopers */
|
||||||
|
|
||||||
|
/* Loops over the gp-frames for a gp-layer, and applies the given callback */
|
||||||
|
short masklayer_frames_looper(MaskLayer *masklay, Scene *scene, short (*masklay_shape_cb)(MaskLayerShape *, Scene *))
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
|
||||||
|
/* error checker */
|
||||||
|
if (masklay == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* do loop */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
|
||||||
|
/* execute callback */
|
||||||
|
if (masklay_shape_cb(masklay_shape, scene))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nothing to return */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ****************************************** */
|
||||||
|
/* Data Conversion Tools */
|
||||||
|
|
||||||
|
/* make a listing all the gp-frames in a layer as cfraelems */
|
||||||
|
void masklayer_make_cfra_list(MaskLayer *masklay, ListBase *elems, short onlysel)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
CfraElem *ce;
|
||||||
|
|
||||||
|
/* error checking */
|
||||||
|
if (ELEM(NULL, masklay, elems))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* loop through gp-frames, adding */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
|
||||||
|
if ((onlysel == 0) || (masklay_shape->flag & MASK_SHAPE_SELECT)) {
|
||||||
|
ce = MEM_callocN(sizeof(CfraElem), "CfraElem");
|
||||||
|
|
||||||
|
ce->cfra = (float)masklay_shape->frame;
|
||||||
|
ce->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? 1 : 0;
|
||||||
|
|
||||||
|
BLI_addtail(elems, ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ***************************************** */
|
||||||
|
/* Selection Tools */
|
||||||
|
|
||||||
|
/* check if one of the frames in this layer is selected */
|
||||||
|
short is_masklayer_frame_selected(MaskLayer *masklay)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
|
||||||
|
/* error checking */
|
||||||
|
if (masklay == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* stop at the first one found */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
|
||||||
|
if (masklay_shape->flag & MASK_SHAPE_SELECT)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not found */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* helper function - select gp-frame based on SELECT_* mode */
|
||||||
|
static void masklayshape_select(MaskLayerShape *masklay_shape, short select_mode)
|
||||||
|
{
|
||||||
|
if (masklay_shape == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (select_mode) {
|
||||||
|
case SELECT_ADD:
|
||||||
|
masklay_shape->flag |= MASK_SHAPE_SELECT;
|
||||||
|
break;
|
||||||
|
case SELECT_SUBTRACT:
|
||||||
|
masklay_shape->flag &= ~MASK_SHAPE_SELECT;
|
||||||
|
break;
|
||||||
|
case SELECT_INVERT:
|
||||||
|
masklay_shape->flag ^= MASK_SHAPE_SELECT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set all/none/invert select (like above, but with SELECT_* modes) */
|
||||||
|
void select_mask_frames(MaskLayer *masklay, short select_mode)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
|
||||||
|
/* error checking */
|
||||||
|
if (masklay == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* handle according to mode */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
|
||||||
|
masklayshape_select(masklay_shape, select_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set all/none/invert select */
|
||||||
|
void set_masklayer_frame_selection(MaskLayer *masklay, short mode)
|
||||||
|
{
|
||||||
|
/* error checking */
|
||||||
|
if (masklay == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* now call the standard function */
|
||||||
|
select_mask_frames(masklay, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* select the frame in this layer that occurs on this frame (there should only be one at most) */
|
||||||
|
void select_mask_frame(MaskLayer *masklay, int selx, short select_mode)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
|
||||||
|
if (masklay == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* search through frames for a match */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
|
||||||
|
/* there should only be one frame with this frame-number */
|
||||||
|
if (masklay_shape->frame == selx) {
|
||||||
|
masklayshape_select(masklay_shape, select_mode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* select the frames in this layer that occur within the bounds specified */
|
||||||
|
void borderselect_masklayer_frames(MaskLayer *masklay, float min, float max, short select_mode)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
|
||||||
|
if (masklay == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* only select those frames which are in bounds */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) {
|
||||||
|
if (IN_RANGE(masklay_shape->frame, min, max))
|
||||||
|
masklayshape_select(masklay_shape, select_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ***************************************** */
|
||||||
|
/* Frame Editing Tools */
|
||||||
|
|
||||||
|
/* Delete selected frames */
|
||||||
|
void delete_masklayer_frames(MaskLayer *masklay)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape, *masklay_shape_next;
|
||||||
|
|
||||||
|
/* error checking */
|
||||||
|
if (masklay == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* check for frames to delete */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape_next) {
|
||||||
|
masklay_shape_next = masklay_shape->next;
|
||||||
|
|
||||||
|
if (masklay_shape->flag & MASK_SHAPE_SELECT)
|
||||||
|
BKE_mask_layer_shape_unlink(masklay, masklay_shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Duplicate selected frames from given gp-layer */
|
||||||
|
void duplicate_masklayer_frames(MaskLayer *masklay)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape, *gpfn;
|
||||||
|
|
||||||
|
/* error checking */
|
||||||
|
if (masklay == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* duplicate selected frames */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = gpfn) {
|
||||||
|
gpfn = masklay_shape->next;
|
||||||
|
|
||||||
|
/* duplicate this frame */
|
||||||
|
if (masklay_shape->flag & MASK_SHAPE_SELECT) {
|
||||||
|
MaskLayerShape *mask_shape_dupe;
|
||||||
|
|
||||||
|
/* duplicate frame, and deselect self */
|
||||||
|
mask_shape_dupe = BKE_mask_layer_shape_duplicate(masklay_shape);
|
||||||
|
masklay_shape->flag &= ~MASK_SHAPE_SELECT;
|
||||||
|
|
||||||
|
// XXX - how to handle duplicate frames?
|
||||||
|
BLI_insertlinkafter(&masklay->splines_shapes, masklay_shape, mask_shape_dupe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -285,6 +285,18 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
|||||||
else glColor4ub(col2[0], col2[1], col2[2], 0x22);
|
else glColor4ub(col2[0], col2[1], col2[2], 0x22);
|
||||||
glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF);
|
glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF);
|
||||||
|
|
||||||
|
/* frames one and higher get a saturated background */
|
||||||
|
if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
|
||||||
|
else glColor4ub(col2[0], col2[1], col2[2], 0x44);
|
||||||
|
glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF);
|
||||||
|
}
|
||||||
|
else if (ac->datatype == ANIMCONT_MASK) {
|
||||||
|
/* TODO --- this is a copy of gpencil */
|
||||||
|
/* frames less than one get less saturated background */
|
||||||
|
if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
|
||||||
|
else glColor4ub(col2[0], col2[1], col2[2], 0x22);
|
||||||
|
glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF);
|
||||||
|
|
||||||
/* frames one and higher get a saturated background */
|
/* frames one and higher get a saturated background */
|
||||||
if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
|
if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
|
||||||
else glColor4ub(col2[0], col2[1], col2[2], 0x44);
|
else glColor4ub(col2[0], col2[1], col2[2], 0x44);
|
||||||
@ -340,6 +352,9 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
|
|||||||
case ALE_GPFRAME:
|
case ALE_GPFRAME:
|
||||||
draw_gpl_channel(v2d, ads, ale->data, y);
|
draw_gpl_channel(v2d, ads, ale->data, y);
|
||||||
break;
|
break;
|
||||||
|
case ALE_MASKLAY:
|
||||||
|
draw_masklay_channel(v2d, ads, ale->data, y);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
#include "RNA_define.h"
|
#include "RNA_define.h"
|
||||||
@ -64,6 +65,7 @@
|
|||||||
#include "ED_screen.h"
|
#include "ED_screen.h"
|
||||||
#include "ED_transform.h"
|
#include "ED_transform.h"
|
||||||
#include "ED_markers.h"
|
#include "ED_markers.h"
|
||||||
|
#include "ED_mask.h"
|
||||||
|
|
||||||
#include "WM_api.h"
|
#include "WM_api.h"
|
||||||
#include "WM_types.h"
|
#include "WM_types.h"
|
||||||
@ -256,6 +258,19 @@ static void get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
|
|||||||
*max = MAX2(*max, gpf->framenum);
|
*max = MAX2(*max, gpf->framenum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ale->datatype == ALE_MASKLAY) {
|
||||||
|
MaskLayer *masklay = ale->data;
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
|
||||||
|
/* find mask layer which is less than or equal to cframe */
|
||||||
|
for (masklay_shape = masklay->splines_shapes.first;
|
||||||
|
masklay_shape;
|
||||||
|
masklay_shape = masklay_shape->next)
|
||||||
|
{
|
||||||
|
*min = MIN2(*min, masklay_shape->frame);
|
||||||
|
*max = MAX2(*max, masklay_shape->frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
FCurve *fcu = (FCurve *)ale->key_data;
|
FCurve *fcu = (FCurve *)ale->key_data;
|
||||||
float tmin, tmax;
|
float tmin, tmax;
|
||||||
@ -476,11 +491,16 @@ static int actkeys_copy_exec(bContext *C, wmOperator *op)
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
/* copy keyframes */
|
/* copy keyframes */
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL) {
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
|
||||||
// FIXME...
|
// FIXME...
|
||||||
BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode");
|
BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode");
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
else if (ac.datatype == ANIMCONT_MASK) {
|
||||||
|
// FIXME...
|
||||||
|
BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode");
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (copy_action_keys(&ac)) {
|
if (copy_action_keys(&ac)) {
|
||||||
BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
|
BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer");
|
||||||
@ -521,9 +541,9 @@ static int actkeys_paste_exec(bContext *C, wmOperator *op)
|
|||||||
ac.reports = op->reports;
|
ac.reports = op->reports;
|
||||||
|
|
||||||
/* paste keyframes */
|
/* paste keyframes */
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL) {
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
|
||||||
// FIXME...
|
// FIXME...
|
||||||
BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil mode");
|
BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for Grease Pencil or Mask mode");
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -625,7 +645,7 @@ static int actkeys_insertkey_exec(bContext *C, wmOperator *op)
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
/* what channels to affect? */
|
/* what channels to affect? */
|
||||||
@ -671,7 +691,7 @@ static void duplicate_action_keys(bAnimContext *ac)
|
|||||||
int filter;
|
int filter;
|
||||||
|
|
||||||
/* filter data */
|
/* filter data */
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||||
@ -681,8 +701,12 @@ static void duplicate_action_keys(bAnimContext *ac)
|
|||||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||||
if (ale->type == ANIMTYPE_FCURVE)
|
if (ale->type == ANIMTYPE_FCURVE)
|
||||||
duplicate_fcurve_keys((FCurve *)ale->key_data);
|
duplicate_fcurve_keys((FCurve *)ale->key_data);
|
||||||
else
|
else if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
duplicate_gplayer_frames((bGPDlayer *)ale->data);
|
duplicate_gplayer_frames((bGPDlayer *)ale->data);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
duplicate_masklayer_frames((MaskLayer *)ale->data);
|
||||||
|
else
|
||||||
|
BLI_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free filtered list */
|
/* free filtered list */
|
||||||
@ -703,7 +727,7 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
duplicate_action_keys(&ac);
|
duplicate_action_keys(&ac);
|
||||||
|
|
||||||
/* validate keyframes after editing */
|
/* validate keyframes after editing */
|
||||||
if (ac.datatype != ANIMCONT_GPENCIL)
|
if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
ANIM_editkeyframes_refresh(&ac);
|
ANIM_editkeyframes_refresh(&ac);
|
||||||
|
|
||||||
/* set notifier that keyframes have changed */
|
/* set notifier that keyframes have changed */
|
||||||
@ -744,7 +768,7 @@ static void delete_action_keys(bAnimContext *ac)
|
|||||||
int filter;
|
int filter;
|
||||||
|
|
||||||
/* filter data */
|
/* filter data */
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||||
@ -752,7 +776,13 @@ static void delete_action_keys(bAnimContext *ac)
|
|||||||
|
|
||||||
/* loop through filtered data and delete selected keys */
|
/* loop through filtered data and delete selected keys */
|
||||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||||
if (ale->type != ANIMTYPE_GPLAYER) {
|
if (ale->type == ANIMTYPE_GPLAYER) {
|
||||||
|
delete_gplayer_frames((bGPDlayer *)ale->data);
|
||||||
|
}
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER) {
|
||||||
|
delete_masklayer_frames((MaskLayer *)ale->data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
FCurve *fcu = (FCurve *)ale->key_data;
|
FCurve *fcu = (FCurve *)ale->key_data;
|
||||||
AnimData *adt = ale->adt;
|
AnimData *adt = ale->adt;
|
||||||
|
|
||||||
@ -763,8 +793,6 @@ static void delete_action_keys(bAnimContext *ac)
|
|||||||
if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
|
if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0))
|
||||||
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
|
ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
delete_gplayer_frames((bGPDlayer *)ale->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* free filtered list */
|
/* free filtered list */
|
||||||
@ -785,7 +813,7 @@ static int actkeys_delete_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
delete_action_keys(&ac);
|
delete_action_keys(&ac);
|
||||||
|
|
||||||
/* validate keyframes after editing */
|
/* validate keyframes after editing */
|
||||||
if (ac.datatype != ANIMCONT_GPENCIL)
|
if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
ANIM_editkeyframes_refresh(&ac);
|
ANIM_editkeyframes_refresh(&ac);
|
||||||
|
|
||||||
/* set notifier that keyframes have changed */
|
/* set notifier that keyframes have changed */
|
||||||
@ -840,7 +868,7 @@ static int actkeys_clean_exec(bContext *C, wmOperator *op)
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get cleaning threshold */
|
/* get cleaning threshold */
|
||||||
@ -907,7 +935,7 @@ static int actkeys_sample_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* sample keyframes */
|
/* sample keyframes */
|
||||||
@ -1014,7 +1042,7 @@ static int actkeys_expo_exec(bContext *C, wmOperator *op)
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get handle setting mode */
|
/* get handle setting mode */
|
||||||
@ -1085,7 +1113,7 @@ static int actkeys_ipo_exec(bContext *C, wmOperator *op)
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get handle setting mode */
|
/* get handle setting mode */
|
||||||
@ -1165,7 +1193,7 @@ static int actkeys_handletype_exec(bContext *C, wmOperator *op)
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get handle setting mode */
|
/* get handle setting mode */
|
||||||
@ -1236,7 +1264,7 @@ static int actkeys_keytype_exec(bContext *C, wmOperator *op)
|
|||||||
/* get editor data */
|
/* get editor data */
|
||||||
if (ANIM_animdata_get_context(C, &ac) == 0)
|
if (ANIM_animdata_get_context(C, &ac) == 0)
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get handle setting mode */
|
/* get handle setting mode */
|
||||||
@ -1359,7 +1387,7 @@ static void snap_action_keys(bAnimContext *ac, short mode)
|
|||||||
KeyframeEditFunc edit_cb;
|
KeyframeEditFunc edit_cb;
|
||||||
|
|
||||||
/* filter data */
|
/* filter data */
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||||
@ -1404,7 +1432,7 @@ static int actkeys_snap_exec(bContext *C, wmOperator *op)
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
// XXX...
|
// XXX...
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get snapping mode */
|
/* get snapping mode */
|
||||||
@ -1482,7 +1510,7 @@ static void mirror_action_keys(bAnimContext *ac, short mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* filter data */
|
/* filter data */
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||||
@ -1518,7 +1546,7 @@ static int actkeys_mirror_exec(bContext *C, wmOperator *op)
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
// XXX...
|
// XXX...
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
return OPERATOR_PASS_THROUGH;
|
return OPERATOR_PASS_THROUGH;
|
||||||
|
|
||||||
/* get mirroring mode */
|
/* get mirroring mode */
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "DNA_gpencil_types.h"
|
#include "DNA_gpencil_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_mask_types.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
#include "RNA_define.h"
|
#include "RNA_define.h"
|
||||||
@ -55,6 +56,7 @@
|
|||||||
|
|
||||||
#include "ED_anim_api.h"
|
#include "ED_anim_api.h"
|
||||||
#include "ED_gpencil.h"
|
#include "ED_gpencil.h"
|
||||||
|
#include "ED_mask.h"
|
||||||
#include "ED_keyframes_draw.h"
|
#include "ED_keyframes_draw.h"
|
||||||
#include "ED_keyframes_edit.h"
|
#include "ED_keyframes_edit.h"
|
||||||
#include "ED_markers.h"
|
#include "ED_markers.h"
|
||||||
@ -92,7 +94,7 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
|
|||||||
KeyframeEditFunc test_cb, sel_cb;
|
KeyframeEditFunc test_cb, sel_cb;
|
||||||
|
|
||||||
/* determine type-based settings */
|
/* determine type-based settings */
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||||
@ -112,6 +114,12 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER) {
|
||||||
|
if (is_masklayer_frame_selected(ale->data)) {
|
||||||
|
sel = SELECT_SUBTRACT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
|
if (ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, test_cb, NULL)) {
|
||||||
sel = SELECT_SUBTRACT;
|
sel = SELECT_SUBTRACT;
|
||||||
@ -128,6 +136,8 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
|
|||||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||||
if (ale->type == ANIMTYPE_GPLAYER)
|
if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
set_gplayer_frame_selection(ale->data, sel);
|
set_gplayer_frame_selection(ale->data, sel);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
set_masklayer_frame_selection(ale->data, sel);
|
||||||
else
|
else
|
||||||
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
|
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -250,6 +260,8 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s
|
|||||||
/* loop over data selecting */
|
/* loop over data selecting */
|
||||||
if (ale->type == ANIMTYPE_GPLAYER)
|
if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
|
borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
borderselect_masklayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
|
||||||
else
|
else
|
||||||
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
|
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -400,6 +412,9 @@ static void markers_selectkeys_between(bAnimContext *ac)
|
|||||||
else if (ale->type == ANIMTYPE_GPLAYER) {
|
else if (ale->type == ANIMTYPE_GPLAYER) {
|
||||||
borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
|
borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
|
||||||
}
|
}
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER) {
|
||||||
|
borderselect_masklayer_frames(ale->data, min, max, SELECT_ADD);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -467,7 +482,7 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
|
|||||||
/* loop through all of the keys and select additional keyframes
|
/* loop through all of the keys and select additional keyframes
|
||||||
* based on the keys found to be selected above
|
* based on the keys found to be selected above
|
||||||
*/
|
*/
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/);
|
||||||
@ -489,6 +504,8 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
|
|||||||
/* select elements with frame number matching cfraelem */
|
/* select elements with frame number matching cfraelem */
|
||||||
if (ale->type == ANIMTYPE_GPLAYER)
|
if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD);
|
select_gpencil_frame(ale->data, ce->cfra, SELECT_ADD);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
select_mask_frame(ale->data, ce->cfra, SELECT_ADD);
|
||||||
else
|
else
|
||||||
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -755,7 +772,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* filter data */
|
/* filter data */
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS);
|
||||||
@ -772,6 +789,8 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
|
|||||||
}
|
}
|
||||||
else if (ale->type == ANIMTYPE_GPLAYER)
|
else if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode);
|
borderselect_gplayer_frames(ale->data, ked.f1, ked.f2, select_mode);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
borderselect_masklayer_frames(ale->data, ked.f1, ked.f2, select_mode);
|
||||||
else
|
else
|
||||||
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -909,6 +928,8 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
|
|||||||
/* select the nominated keyframe on the given frame */
|
/* select the nominated keyframe on the given frame */
|
||||||
if (ale->type == ANIMTYPE_GPLAYER)
|
if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
select_gpencil_frame(ale->data, selx, select_mode);
|
select_gpencil_frame(ale->data, selx, select_mode);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
select_mask_frame(ale->data, selx, select_mode);
|
||||||
else
|
else
|
||||||
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
|
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -933,7 +954,7 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
|
|||||||
/* loop through all of the keys and select additional keyframes
|
/* loop through all of the keys and select additional keyframes
|
||||||
* based on the keys found to be selected above
|
* based on the keys found to be selected above
|
||||||
*/
|
*/
|
||||||
if (ac->datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac->datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_CURVESONLY */ | ANIMFILTER_NODUPLIS);
|
||||||
else
|
else
|
||||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
|
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS);
|
||||||
@ -951,6 +972,8 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
|
|||||||
/* select elements with frame number matching cfra */
|
/* select elements with frame number matching cfra */
|
||||||
if (ale->type == ANIMTYPE_GPLAYER)
|
if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
select_gpencil_frame(ale->key_data, selx, select_mode);
|
select_gpencil_frame(ale->key_data, selx, select_mode);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
select_mask_frame(ale->key_data, selx, select_mode);
|
||||||
else
|
else
|
||||||
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -1051,6 +1074,11 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
|
|||||||
bGPDlayer *gpl = (bGPDlayer *)ale->data;
|
bGPDlayer *gpl = (bGPDlayer *)ale->data;
|
||||||
gpl_to_keylist(ads, gpl, &anim_keys);
|
gpl_to_keylist(ads, gpl, &anim_keys);
|
||||||
}
|
}
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER) {
|
||||||
|
// TODO: why don't we just give masklayers key_data too?
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
mask_to_keylist(ads, masklay, &anim_keys);
|
||||||
|
}
|
||||||
|
|
||||||
/* start from keyframe at root of BST, traversing until we find one within the range that was clicked on */
|
/* 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) {
|
for (ak = anim_keys.root; ak; ak = akn) {
|
||||||
@ -1120,6 +1148,18 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
|
|||||||
//gpencil_layer_setactive(gpd, gpl);
|
//gpencil_layer_setactive(gpd, gpl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ac->datatype == ANIMCONT_MASK) {
|
||||||
|
/* deselect all other channels first */
|
||||||
|
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
|
||||||
|
|
||||||
|
/* Highlight GPencil Layer */
|
||||||
|
if ((ale && ale->data) && (ale->type == ANIMTYPE_MASKLAYER)) {
|
||||||
|
MaskLayer *masklay = ale->data;
|
||||||
|
|
||||||
|
masklay->flag |= MASK_LAYERFLAG_SELECT;
|
||||||
|
//gpencil_layer_setactive(gpd, gpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only select keyframes if we clicked on a valid channel and hit something */
|
/* only select keyframes if we clicked on a valid channel and hit something */
|
||||||
|
@ -555,7 +555,7 @@ struct wmKeyMap *transform_modal_keymap(struct wmKeyConfig *keyconf);
|
|||||||
/*********************** transform_conversions.c ********** */
|
/*********************** transform_conversions.c ********** */
|
||||||
struct ListBase;
|
struct ListBase;
|
||||||
|
|
||||||
void flushTransGPactionData(TransInfo *t);
|
void flushTransIntFrameActionData(TransInfo *t);
|
||||||
void flushTransGraphData(TransInfo *t);
|
void flushTransGraphData(TransInfo *t);
|
||||||
void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
|
void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data);
|
||||||
void flushTransUVs(TransInfo *t);
|
void flushTransUVs(TransInfo *t);
|
||||||
|
@ -2797,6 +2797,99 @@ static void posttrans_gpd_clean (bGPdata *gpd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Called by special_aftertrans_update to make sure selected gp-frames replace
|
||||||
|
* any other gp-frames which may reside on that frame (that are not selected).
|
||||||
|
* It also makes sure sorted are still stored in chronological order after
|
||||||
|
* transform.
|
||||||
|
*/
|
||||||
|
static void posttrans_mask_clean(Mask *mask)
|
||||||
|
{
|
||||||
|
MaskLayer *masklay;
|
||||||
|
|
||||||
|
for (masklay = mask->masklayers.first; masklay; masklay= masklay->next) {
|
||||||
|
ListBase sel_buffer = {NULL, NULL};
|
||||||
|
MaskLayerShape *masklay_shape, *masklay_shape_new;
|
||||||
|
MaskLayerShape *masklay_shape_sort, *masklay_shape_sort_new;
|
||||||
|
|
||||||
|
/* loop 1: loop through and isolate selected gp-frames to buffer
|
||||||
|
* (these need to be sorted as they are isolated)
|
||||||
|
*/
|
||||||
|
for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape_new) {
|
||||||
|
short added= 0;
|
||||||
|
masklay_shape_new= masklay_shape->next;
|
||||||
|
|
||||||
|
if (masklay_shape->flag & GP_FRAME_SELECT) {
|
||||||
|
BLI_remlink(&masklay->splines_shapes, masklay_shape);
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
*/
|
||||||
|
for (masklay_shape_sort= sel_buffer.last; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort->prev) {
|
||||||
|
/* if current (masklay_shape) occurs after this one in buffer, add! */
|
||||||
|
if (masklay_shape_sort->frame < masklay_shape->frame) {
|
||||||
|
BLI_insertlinkafter(&sel_buffer, masklay_shape_sort, masklay_shape);
|
||||||
|
added= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (added == 0)
|
||||||
|
BLI_addhead(&sel_buffer, masklay_shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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. masklay->splines_shapes is empty), then just transfer sel-buf over */
|
||||||
|
if (masklay->splines_shapes.first == NULL) {
|
||||||
|
masklay->splines_shapes.first= sel_buffer.first;
|
||||||
|
masklay->splines_shapes.last= sel_buffer.last;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* loop 2: remove duplicates of splines_shapes in buffers */
|
||||||
|
for (masklay_shape= masklay->splines_shapes.first; masklay_shape && sel_buffer.first; masklay_shape= masklay_shape_new) {
|
||||||
|
masklay_shape_new= masklay_shape->next;
|
||||||
|
|
||||||
|
/* loop through sel_buffer, emptying stuff from front of buffer if ok */
|
||||||
|
for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort && masklay_shape; masklay_shape_sort= masklay_shape_sort_new) {
|
||||||
|
masklay_shape_sort_new= masklay_shape_sort->next;
|
||||||
|
|
||||||
|
/* if this buffer frame needs to go before current, add it! */
|
||||||
|
if (masklay_shape_sort->frame < masklay_shape->frame) {
|
||||||
|
/* transfer buffer frame to splines_shapes list (before current) */
|
||||||
|
BLI_remlink(&sel_buffer, masklay_shape_sort);
|
||||||
|
BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort);
|
||||||
|
}
|
||||||
|
/* if this buffer frame is on same frame, replace current with it and stop */
|
||||||
|
else if (masklay_shape_sort->frame == masklay_shape->frame) {
|
||||||
|
/* transfer buffer frame to splines_shapes list (before current) */
|
||||||
|
BLI_remlink(&sel_buffer, masklay_shape_sort);
|
||||||
|
BLI_insertlinkbefore(&masklay->splines_shapes, masklay_shape, masklay_shape_sort);
|
||||||
|
|
||||||
|
/* get rid of current frame */
|
||||||
|
BKE_mask_layer_shape_unlink(masklay, masklay_shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if anything is still in buffer, append to end */
|
||||||
|
for (masklay_shape_sort= sel_buffer.first; masklay_shape_sort; masklay_shape_sort= masklay_shape_sort_new) {
|
||||||
|
masklay_shape_sort_new= masklay_shape_sort->next;
|
||||||
|
|
||||||
|
BLI_remlink(&sel_buffer, masklay_shape_sort);
|
||||||
|
BLI_addtail(&masklay->splines_shapes, masklay_shape_sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: this is the only difference to grease pencil code above */
|
||||||
|
BKE_mask_layer_shape_sort(masklay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Called during special_aftertrans_update to make sure selected keyframes replace
|
/* Called during special_aftertrans_update to make sure selected keyframes replace
|
||||||
* any other keyframes which may reside on that frame (that is not selected).
|
* any other keyframes which may reside on that frame (that is not selected).
|
||||||
*/
|
*/
|
||||||
@ -2936,6 +3029,27 @@ static int count_gplayer_frames(bGPDlayer *gpl, char side, float cfra)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fully select selected beztriples, but only include if it's on the right side of cfra */
|
||||||
|
static int count_masklayer_frames(MaskLayer *masklay, char side, float cfra)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklayer_shape;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (masklay == NULL)
|
||||||
|
return count;
|
||||||
|
|
||||||
|
/* only include points that occur on the right side of cfra */
|
||||||
|
for (masklayer_shape= masklay->splines_shapes.first; masklayer_shape; masklayer_shape= masklayer_shape->next) {
|
||||||
|
if (masklayer_shape->flag & MASK_SHAPE_SELECT) {
|
||||||
|
if (FrameOnMouseSide(side, (float)masklayer_shape->frame, cfra))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This function assigns the information to transdata */
|
/* This function assigns the information to transdata */
|
||||||
static void TimeToTransData(TransData *td, float *time, AnimData *adt)
|
static void TimeToTransData(TransData *td, float *time, AnimData *adt)
|
||||||
{
|
{
|
||||||
@ -2998,7 +3112,7 @@ typedef struct tGPFtransdata {
|
|||||||
} tGPFtransdata;
|
} tGPFtransdata;
|
||||||
|
|
||||||
/* This function helps flush transdata written to tempdata into the gp-frames */
|
/* This function helps flush transdata written to tempdata into the gp-frames */
|
||||||
void flushTransGPactionData(TransInfo *t)
|
void flushTransIntFrameActionData(TransInfo *t)
|
||||||
{
|
{
|
||||||
tGPFtransdata *tfd;
|
tGPFtransdata *tfd;
|
||||||
int i;
|
int i;
|
||||||
@ -3049,6 +3163,35 @@ static int GPLayerToTransData (TransData *td, tGPFtransdata *tfd, bGPDlayer *gpl
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* refer to comment above #GPLayerToTransData, this is the same but for masks */
|
||||||
|
static int MaskLayerToTransData(TransData *td, tGPFtransdata *tfd, MaskLayer *masklay, char side, float cfra)
|
||||||
|
{
|
||||||
|
MaskLayerShape *masklay_shape;
|
||||||
|
int count= 0;
|
||||||
|
|
||||||
|
/* check for select frames on right side of current frame */
|
||||||
|
for (masklay_shape= masklay->splines_shapes.first; masklay_shape; masklay_shape= masklay_shape->next) {
|
||||||
|
if (masklay_shape->flag & MASK_SHAPE_SELECT) {
|
||||||
|
if (FrameOnMouseSide(side, (float)masklay_shape->frame, cfra)) {
|
||||||
|
/* memory is calloc'ed, so that should zero everything nicely for us */
|
||||||
|
td->val= &tfd->val;
|
||||||
|
td->ival= (float)masklay_shape->frame;
|
||||||
|
|
||||||
|
tfd->val= (float)masklay_shape->frame;
|
||||||
|
tfd->sdata= &masklay_shape->frame;
|
||||||
|
|
||||||
|
/* advance td now */
|
||||||
|
td++;
|
||||||
|
tfd++;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void createTransActionData(bContext *C, TransInfo *t)
|
static void createTransActionData(bContext *C, TransInfo *t)
|
||||||
{
|
{
|
||||||
Scene *scene= t->scene;
|
Scene *scene= t->scene;
|
||||||
@ -3069,7 +3212,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* filter data */
|
/* filter data */
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL)
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
|
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT);
|
||||||
else
|
else
|
||||||
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
|
filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT /*| ANIMFILTER_CURVESONLY*/);
|
||||||
@ -3102,8 +3245,12 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
|||||||
|
|
||||||
if (ale->type == ANIMTYPE_FCURVE)
|
if (ale->type == ANIMTYPE_FCURVE)
|
||||||
count += count_fcurve_keys(ale->key_data, t->frame_side, cfra);
|
count += count_fcurve_keys(ale->key_data, t->frame_side, cfra);
|
||||||
else
|
else if (ale->type == ANIMTYPE_GPLAYER)
|
||||||
count += count_gplayer_frames(ale->data, t->frame_side, cfra);
|
count += count_gplayer_frames(ale->data, t->frame_side, cfra);
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER)
|
||||||
|
count += count_masklayer_frames(ale->data, t->frame_side, cfra);
|
||||||
|
else
|
||||||
|
BLI_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stop if trying to build list if nothing selected */
|
/* stop if trying to build list if nothing selected */
|
||||||
@ -3121,7 +3268,7 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
|||||||
td= t->data;
|
td= t->data;
|
||||||
td2d = t->data2d;
|
td2d = t->data2d;
|
||||||
|
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL) {
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
|
||||||
if (t->mode == TFM_TIME_SLIDE) {
|
if (t->mode == TFM_TIME_SLIDE) {
|
||||||
t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata");
|
t->customData= MEM_callocN((sizeof(float)*2)+(sizeof(tGPFtransdata)*count), "TimeSlide + tGPFtransdata");
|
||||||
tfd= (tGPFtransdata *)((float *)(t->customData) + 2);
|
tfd= (tGPFtransdata *)((float *)(t->customData) + 2);
|
||||||
@ -3144,6 +3291,14 @@ static void createTransActionData(bContext *C, TransInfo *t)
|
|||||||
td += i;
|
td += i;
|
||||||
tfd += i;
|
tfd += i;
|
||||||
}
|
}
|
||||||
|
else if (ale->type == ANIMTYPE_MASKLAYER) {
|
||||||
|
MaskLayer *masklay = (MaskLayer *)ale->data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = MaskLayerToTransData(td, tfd, masklay, t->frame_side, cfra);
|
||||||
|
td += i;
|
||||||
|
tfd += i;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
AnimData *adt= ANIM_nla_mapping_get(&ac, ale);
|
||||||
FCurve *fcu= (FCurve *)ale->key_data;
|
FCurve *fcu= (FCurve *)ale->key_data;
|
||||||
@ -5004,6 +5159,26 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (ac.datatype == ANIMCONT_MASK) {
|
||||||
|
/* remove duplicate frames and also make sure points are in order! */
|
||||||
|
/* 3 cases here for curve cleanups:
|
||||||
|
* 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done
|
||||||
|
* 2) canceled == 0 -> user confirmed the transform, so duplicates should be removed
|
||||||
|
* 3) canceled + duplicate -> user canceled the transform, but we made duplicates, so get rid of these
|
||||||
|
*/
|
||||||
|
if ((saction->flag & SACTION_NOTRANSKEYCULL)==0 &&
|
||||||
|
((canceled == 0) || (duplicate)))
|
||||||
|
{
|
||||||
|
Mask *mask;
|
||||||
|
|
||||||
|
// XXX: BAD! this get gpencil datablocks directly from main db...
|
||||||
|
// but that's how this currently works :/
|
||||||
|
for (mask = G.main->mask.first; mask; mask = mask->id.next) {
|
||||||
|
if (ID_REAL_USERS(mask))
|
||||||
|
posttrans_mask_clean(mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* marker transform, not especially nice but we may want to move markers
|
/* marker transform, not especially nice but we may want to move markers
|
||||||
* at the same time as keyframes in the dope sheet.
|
* at the same time as keyframes in the dope sheet.
|
||||||
@ -5027,7 +5202,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* make sure all F-Curves are set correctly */
|
/* make sure all F-Curves are set correctly */
|
||||||
if (ac.datatype != ANIMCONT_GPENCIL)
|
if (!ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK))
|
||||||
ANIM_editkeyframes_refresh(&ac);
|
ANIM_editkeyframes_refresh(&ac);
|
||||||
|
|
||||||
/* clear flag that was set for time-slide drawing */
|
/* clear flag that was set for time-slide drawing */
|
||||||
|
@ -350,9 +350,9 @@ static void recalcData_actedit(TransInfo *t)
|
|||||||
ANIM_animdata_context_getdata(&ac);
|
ANIM_animdata_context_getdata(&ac);
|
||||||
|
|
||||||
/* perform flush */
|
/* perform flush */
|
||||||
if (ac.datatype == ANIMCONT_GPENCIL) {
|
if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
|
||||||
/* flush transform values back to actual coordinates */
|
/* flush transform values back to actual coordinates */
|
||||||
flushTransGPactionData(t);
|
flushTransIntFrameActionData(t);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
|
/* get animdata blocks visible in editor, assuming that these will be the ones where things changed */
|
||||||
|
@ -632,7 +632,9 @@ typedef enum eAnimEdit_Context {
|
|||||||
/* editing of gpencil data */
|
/* editing of gpencil data */
|
||||||
SACTCONT_GPENCIL = 2,
|
SACTCONT_GPENCIL = 2,
|
||||||
/* dopesheet (default) */
|
/* dopesheet (default) */
|
||||||
SACTCONT_DOPESHEET = 3
|
SACTCONT_DOPESHEET = 3,
|
||||||
|
/* mask */
|
||||||
|
SACTCONT_MASK = 4
|
||||||
} eAnimEdit_Context;
|
} eAnimEdit_Context;
|
||||||
|
|
||||||
/* SpaceAction AutoSnap Settings (also used by other Animation Editors) */
|
/* SpaceAction AutoSnap Settings (also used by other Animation Editors) */
|
||||||
|
@ -48,6 +48,9 @@ typedef struct Mask {
|
|||||||
int masklay_tot; /* total number of mask layers */
|
int masklay_tot; /* total number of mask layers */
|
||||||
|
|
||||||
int sfra, efra; /* frames, used by the sequencer */
|
int sfra, efra; /* frames, used by the sequencer */
|
||||||
|
|
||||||
|
int flag; /* for anim info */
|
||||||
|
int pad;
|
||||||
} Mask;
|
} Mask;
|
||||||
|
|
||||||
typedef struct MaskParent {
|
typedef struct MaskParent {
|
||||||
@ -96,7 +99,7 @@ typedef struct MaskLayerShape {
|
|||||||
float *data; /* u coordinate along spline segment and weight of this point */
|
float *data; /* u coordinate along spline segment and weight of this point */
|
||||||
int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */
|
int tot_vert; /* to ensure no buffer overruns's: alloc size is (tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE) */
|
||||||
int frame; /* different flags of this point */
|
int frame; /* different flags of this point */
|
||||||
char flag;
|
char flag; /* animation flag */
|
||||||
char pad[7];
|
char pad[7];
|
||||||
} MaskLayerShape;
|
} MaskLayerShape;
|
||||||
|
|
||||||
@ -125,9 +128,8 @@ typedef struct MaskLayer {
|
|||||||
char blend;
|
char blend;
|
||||||
char blend_flag;
|
char blend_flag;
|
||||||
|
|
||||||
//char flag; /* not used yet */
|
char flag; /* for animation */
|
||||||
char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */
|
char restrictflag; /* matching 'Object' flag of the same name - eventually use in the outliner */
|
||||||
char pad[1];
|
|
||||||
} MaskLayer;
|
} MaskLayer;
|
||||||
|
|
||||||
/* MaskParent->flag */
|
/* MaskParent->flag */
|
||||||
@ -169,4 +171,21 @@ enum {
|
|||||||
MASK_BLENDFLAG_INVERT = (1 << 0)
|
MASK_BLENDFLAG_INVERT = (1 << 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* masklay->flag */
|
||||||
|
enum {
|
||||||
|
MASK_LAYERFLAG_LOCKED = (1 << 4),
|
||||||
|
MASK_LAYERFLAG_SELECT = (1 << 5)
|
||||||
|
};
|
||||||
|
|
||||||
|
/* masklay_shape->flag */
|
||||||
|
enum {
|
||||||
|
MASK_SHAPE_SELECT = (1 << 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* mask->flag */
|
||||||
|
enum {
|
||||||
|
MASK_ANIMF_EXPAND = (1 << 4)
|
||||||
|
};
|
||||||
|
|
||||||
#endif // __DNA_MASK_TYPES_H__
|
#endif // __DNA_MASK_TYPES_H__
|
||||||
|
@ -2229,6 +2229,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna)
|
|||||||
{SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"},
|
{SACTCONT_ACTION, "ACTION", ICON_OBJECT_DATA, "Action Editor", "Action Editor"},
|
||||||
{SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"},
|
{SACTCONT_SHAPEKEY, "SHAPEKEY", ICON_SHAPEKEY_DATA, "ShapeKey Editor", "ShapeKey Editor"},
|
||||||
{SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"},
|
{SACTCONT_GPENCIL, "GPENCIL", ICON_GREASEPENCIL, "Grease Pencil", "Grease Pencil"},
|
||||||
|
{SACTCONT_MASK, "MASK", ICON_MOD_MASK, "Mask", "Mask Editor"},
|
||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user