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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/CMakeLists.txt7
-rw-r--r--source/blender/editors/animation/SConscript2
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c425
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c604
-rw-r--r--source/blender/editors/animation/anim_deps.c9
-rw-r--r--source/blender/editors/animation/anim_draw.c30
-rw-r--r--source/blender/editors/animation/anim_filter.c2026
-rw-r--r--source/blender/editors/animation/anim_intern.h7
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c21
-rw-r--r--source/blender/editors/animation/anim_markers.c167
-rw-r--r--source/blender/editors/animation/anim_ops.c34
-rw-r--r--source/blender/editors/animation/drivers.c20
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c149
-rw-r--r--source/blender/editors/animation/keyframes_draw.c275
-rw-r--r--source/blender/editors/animation/keyframes_edit.c258
-rw-r--r--source/blender/editors/animation/keyframes_general.c64
-rw-r--r--source/blender/editors/animation/keyframing.c115
-rw-r--r--source/blender/editors/animation/keyingsets.c62
18 files changed, 1943 insertions, 2332 deletions
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 66ec9cf75d6..a3c1d035d9b 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -22,6 +22,7 @@
set(INC
../include
../../blenkernel
+ ../../blenloader
../../blenlib
../../makesdna
../../makesrna
@@ -29,6 +30,10 @@ set(INC
../../../../intern/guardedalloc
)
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
set(SRC
anim_channels_defines.c
anim_channels_edit.c
@@ -49,4 +54,4 @@ set(SRC
anim_intern.h
)
-blender_add_lib(bf_editor_animation "${SRC}" "${INC}")
+blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/animation/SConscript b/source/blender/editors/animation/SConscript
index 4597a612c7c..96b05b8bccc 100644
--- a/source/blender/editors/animation/SConscript
+++ b/source/blender/editors/animation/SConscript
@@ -4,6 +4,6 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
-incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
+incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include ../../blenloader'
env.BlenderLib ( 'bf_editors_animation', sources, Split(incs), [], libtype=['core'], priority=[125] )
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index b2ee2f008f5..5e23b49fc22 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -25,6 +25,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_channels_defines.c
+ * \ingroup edanimation
+ */
+
+
#include <stdio.h>
#include "MEM_guardedalloc.h"
@@ -154,8 +159,8 @@ static void acf_generic_channel_color(bAnimContext *ac, bAnimListElem *ale, floa
short indent= (acf->get_indent_level) ? acf->get_indent_level(ac, ale) : 0;
/* get context info needed... */
- if ((ac->sa) && (ac->sa->spacetype == SPACE_ACTION))
- saction= (SpaceAction *)ac->sa->spacedata.first;
+ if ((ac->sl) && (ac->spacetype == SPACE_ACTION))
+ saction= (SpaceAction *)ac->sl;
if (ale->type == ANIMTYPE_FCURVE) {
FCurve *fcu= (FCurve *)ale->data;
@@ -230,13 +235,6 @@ static short acf_generic_indention_flexible(bAnimContext *UNUSED(ac), bAnimListE
{
short indent= 0;
- if (ale->id) {
- /* special exception for materials, textures, and particles */
- // xxx should tex use indention 2?
- if (ELEM3(GS(ale->id->name),ID_MA,ID_PA,ID_TE))
- indent++;
- }
-
/* grouped F-Curves need extra level of indention */
if (ale->type == ANIMTYPE_FCURVE) {
FCurve *fcu= (FCurve *)ale->data;
@@ -261,36 +259,53 @@ static short acf_generic_basic_offset(bAnimContext *ac, bAnimListElem *ale)
return 0;
}
+/* offset based on nodetree type */
+static short acf_nodetree_rootType_offset(bNodeTree *ntree)
+{
+ if (ntree) {
+ switch (ntree->type) {
+ case NTREE_SHADER:
+ /* 1 additional level (i.e. is indented one level in from material,
+ * so shift all right by one step)
+ */
+ return INDENT_STEP_SIZE;
+
+ case NTREE_COMPOSIT:
+ /* no additional levels needed */
+ return 0;
+
+ case NTREE_TEXTURE:
+ /* 2 additional levels */
+ return INDENT_STEP_SIZE*2;
+ }
+ }
+
+ // unknown
+ return 0;
+}
+
/* offset for groups + grouped entities */
static short acf_generic_group_offset(bAnimContext *ac, bAnimListElem *ale)
{
short offset= acf_generic_basic_offset(ac, ale);
if (ale->id) {
- /* special exception for textures */
+ /* texture animdata */
if (GS(ale->id->name) == ID_TE) {
- /* minimum offset */
offset += 21;
-
- /* special offset from owner type */
- switch (ale->ownertype) {
- case ANIMTYPE_DSMAT:
- offset += 21;
- break;
-
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSWOR:
- offset += 14;
- break;
- }
}
- /* special exception for materials and particles */
+ /* materials and particles animdata */
else if (ELEM(GS(ale->id->name),ID_MA,ID_PA))
- offset += 21;
+ offset += 14;
- /* if not in Action Editor mode, groupings must carry some offset too... */
+ /* if not in Action Editor mode, action-groups (and their children) must carry some offset too... */
else if (ac->datatype != ANIMCONT_ACTION)
offset += 14;
+
+ /* nodetree animdata */
+ if (GS(ale->id->name) == ID_NT) {
+ offset += acf_nodetree_rootType_offset((bNodeTree*)ale->id);
+ }
}
/* offset is just the normal type - i.e. based on indention */
@@ -319,46 +334,6 @@ static short acf_generic_none_setting_valid(bAnimContext *ac, bAnimListElem *ale
}
#endif
-/* check if some setting exists for this object-based data-expander (category only) */
-static short acf_generic_dsexpand_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
-{
- switch (setting) {
- /* only expand supported everywhere */
- case ACHANNEL_SETTING_EXPAND:
- return 1;
-
- /* visible
- * - only available in Graph Editor
- * - NOT available for 'filler' channels
- */
- case ACHANNEL_SETTING_VISIBLE:
- if (ELEM3(ale->type, ANIMTYPE_FILLMATD, ANIMTYPE_FILLPARTD, ANIMTYPE_FILLTEXD))
- return 0;
- else
- return ((ac) && (ac->spacetype == SPACE_IPO));
-
- default:
- return 0;
- }
-}
-
-/* get pointer to the setting (category only) */
-static void *acf_generic_dsexpand_setting_ptr(bAnimListElem *ale, int setting, short *type)
-{
- Object *ob= (Object *)ale->data;
-
- /* clear extra return data first */
- *type= 0;
-
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- GET_ACF_FLAG_PTR(ob->nlaflag); // XXX
-
- default: /* unsupported */
- return NULL;
- }
-}
-
/* check if some setting exists for this object-based data-expander (datablock only) */
static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), int setting)
{
@@ -454,8 +429,8 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale, int setting, short *typ
/* if data is valid, return pointer to active dopesheet's relevant flag
* - this is restricted to DopeSheet/Action Editor only
*/
- if ((ac->sa) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
- SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+ if ((ac->sl) && (ac->spacetype == SPACE_ACTION) && (setting == ACHANNEL_SETTING_EXPAND)) {
+ SpaceAction *saction= (SpaceAction *)ac->sl;
bDopeSheet *ads= &saction->ads;
/* return pointer to DopeSheet's flag */
@@ -464,7 +439,7 @@ static void *acf_summary_setting_ptr(bAnimListElem *ale, int setting, short *typ
else {
/* can't return anything useful - unsupported */
*type= 0;
- return 0;
+ return NULL;
}
}
@@ -565,7 +540,7 @@ static void *acf_scene_setting_ptr(bAnimListElem *ale, int setting, short *type)
return NULL;
default: /* unsupported */
- return 0;
+ return NULL;
}
}
@@ -709,7 +684,7 @@ static void *acf_object_setting_ptr(bAnimListElem *ale, int setting, short *type
return NULL;
default: /* unsupported */
- return 0;
+ return NULL;
}
}
@@ -777,7 +752,7 @@ static short acf_group_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale
/* for now, all settings are supported, though some are only conditionally */
switch (setting) {
case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
- return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO));
+ return (ac->spacetype==SPACE_IPO);
default: /* always supported */
return 1;
@@ -874,7 +849,7 @@ static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int
return 0; // NOTE: in this special case, we need to draw ICON_ZOOMOUT
case ACHANNEL_SETTING_VISIBLE: /* Only available in Graph Editor */
- return ((ac->sa) && (ac->sa->spacetype==SPACE_IPO));
+ return (ac->spacetype==SPACE_IPO);
/* always available */
default:
@@ -990,13 +965,13 @@ static void *acf_fillactd_setting_ptr(bAnimListElem *ale, int setting, short *ty
GET_ACF_FLAG_PTR(adt->flag);
}
else
- return 0;
+ return NULL;
case ACHANNEL_SETTING_EXPAND: /* expanded */
GET_ACF_FLAG_PTR(act->flag);
default: /* unsupported */
- return 0;
+ return NULL;
}
}
@@ -1023,7 +998,7 @@ static bAnimChannelType ACF_FILLACTD =
// TODO: just get this from RNA?
static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale))
{
- return ICON_ANIM_DATA;
+ return ICON_DRIVER;
}
static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name)
@@ -1074,7 +1049,7 @@ static void *acf_filldrivers_setting_ptr(bAnimListElem *ale, int setting, short
GET_ACF_FLAG_PTR(adt->flag);
default: /* unsupported */
- return 0;
+ return NULL;
}
}
@@ -1096,203 +1071,6 @@ static bAnimChannelType ACF_FILLDRIVERS =
acf_filldrivers_setting_ptr /* pointer for setting */
};
-/* Materials Expander ------------------------------------------- */
-
-// TODO: just get this from RNA?
-static int acf_fillmatd_icon(bAnimListElem *UNUSED(ale))
-{
- return ICON_MATERIAL_DATA;
-}
-
-static void acf_fillmatd_name(bAnimListElem *UNUSED(ale), char *name)
-{
- BLI_strncpy(name, "Materials", ANIM_CHAN_NAME_SIZE);
-}
-
-/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_fillmatd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
-{
- /* clear extra return data first */
- *neg= 0;
-
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return OB_ADS_SHOWMATS;
-
- default: /* unsupported */
- return 0;
- }
-}
-
-/* materials expander type define */
-static bAnimChannelType ACF_FILLMATD=
-{
- "Materials Filler", /* type name */
-
- acf_generic_dataexpand_color, /* backdrop color */
- acf_generic_dataexpand_backdrop,/* backdrop */
- acf_generic_indention_1, /* indent level */
- acf_generic_basic_offset, /* offset */
-
- acf_fillmatd_name, /* name */
- acf_fillmatd_icon, /* icon */
-
- acf_generic_dsexpand_setting_valid, /* has setting */
- acf_fillmatd_setting_flag, /* flag for setting */
- acf_generic_dsexpand_setting_ptr /* pointer for setting */
-};
-
-/* Particles Expander ------------------------------------------- */
-
-// TODO: just get this from RNA?
-static int acf_fillpartd_icon(bAnimListElem *UNUSED(ale))
-{
- return ICON_PARTICLE_DATA;
-}
-
-static void acf_fillpartd_name(bAnimListElem *UNUSED(ale), char *name)
-{
- BLI_strncpy(name, "Particles", ANIM_CHAN_NAME_SIZE);
-}
-
-/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_fillpartd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
-{
- /* clear extra return data first */
- *neg= 0;
-
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- return OB_ADS_SHOWPARTS;
-
- default: /* unsupported */
- return 0;
- }
-}
-
-/* particles expander type define */
-static bAnimChannelType ACF_FILLPARTD=
-{
- "Particles Filler", /* type name */
-
- acf_generic_dataexpand_color, /* backdrop color */
- acf_generic_dataexpand_backdrop,/* backdrop */
- acf_generic_indention_1, /* indent level */
- acf_generic_basic_offset, /* offset */
-
- acf_fillpartd_name, /* name */
- acf_fillpartd_icon, /* icon */
-
- acf_generic_dsexpand_setting_valid, /* has setting */
- acf_fillpartd_setting_flag, /* flag for setting */
- acf_generic_dsexpand_setting_ptr /* pointer for setting */
-};
-
-/* Textures Expander ------------------------------------------- */
-
-/* offset for groups + grouped entities */
-static short acf_filltexd_offset(bAnimContext *ac, bAnimListElem *ale)
-{
- short offset= acf_generic_basic_offset(ac, ale);
-
- if (ale->id) {
- /* materials */
- switch (GS(ale->id->name)) {
- case ID_MA:
- offset += 21;
- break;
-
- case ID_LA:
- case ID_WO:
- offset += 14;
- break;
- }
- }
-
- return offset;
-}
-
-// TODO: just get this from RNA?
-static int acf_filltexd_icon(bAnimListElem *UNUSED(ale))
-{
- return ICON_TEXTURE_DATA;
-}
-
-static void acf_filltexd_name(bAnimListElem *UNUSED(ale), char *name)
-{
- BLI_strncpy(name, "Textures", ANIM_CHAN_NAME_SIZE);
-}
-
-/* get pointer to the setting (category only) */
-static void *acf_filltexd_setting_ptr(bAnimListElem *ale, int setting, short *type)
-{
- ID *id= (ID *)ale->data;
-
- /* clear extra return data first */
- *type= 0;
-
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- {
- switch (GS(id->name)) {
- case ID_MA:
- {
- Material *ma= (Material *)id;
- GET_ACF_FLAG_PTR(ma->flag);
- }
-
- case ID_LA:
- {
- Lamp *la= (Lamp *)id;
- GET_ACF_FLAG_PTR(la->flag);
- }
-
- case ID_WO:
- {
- World *wo= (World *)id;
- GET_ACF_FLAG_PTR(wo->flag);
- }
- }
- }
-
- default: /* unsupported */
- return NULL;
- }
-}
-
-/* get the appropriate flag(s) for the setting when it is valid */
-static int acf_filltexd_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
-{
- /* clear extra return data first */
- *neg= 0;
-
- switch (setting) {
- case ACHANNEL_SETTING_EXPAND: /* expanded */
- /* NOTE: the exact same flag must be used for other texture stack types too! */
- return MA_DS_SHOW_TEXS;
-
- default: /* unsupported */
- return 0;
- }
-}
-
-/* particles expander type define */
-static bAnimChannelType ACF_FILLTEXD=
-{
- "Textures Filler", /* type name */
-
- acf_generic_dataexpand_color, /* backdrop color */
- acf_generic_dataexpand_backdrop,/* backdrop */
- acf_generic_indention_flexible, /* indent level */
- acf_filltexd_offset, /* offset */
-
- acf_filltexd_name, /* name */
- acf_filltexd_icon, /* icon */
-
- acf_generic_dsexpand_setting_valid, /* has setting */
- acf_filltexd_setting_flag, /* flag for setting */
- acf_filltexd_setting_ptr /* pointer for setting */
-};
/* Material Expander ------------------------------------------- */
@@ -1302,12 +1080,6 @@ static int acf_dsmat_icon(bAnimListElem *UNUSED(ale))
return ICON_MATERIAL_DATA;
}
-/* offset for material expanders */
-static short acf_dsmat_offset(bAnimContext *UNUSED(ac), bAnimListElem *UNUSED(ale))
-{
- return 21;
-}
-
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_dsmat_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
{
@@ -1363,10 +1135,10 @@ static bAnimChannelType ACF_DSMAT=
{
"Material Data Expander", /* type name */
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
- acf_dsmat_offset, /* offset */
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop,/* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_dsmat_icon, /* icon */
@@ -1461,22 +1233,10 @@ static int acf_dstex_icon(bAnimListElem *UNUSED(ale))
}
/* offset for texture expanders */
+// FIXME: soon to be obsolete?
static short acf_dstex_offset(bAnimContext *UNUSED(ac), bAnimListElem *ale)
{
- short offset = 21;
-
- /* special offset from owner type */
- // FIXME: too much now!
- switch (ale->ownertype) {
- case ANIMTYPE_DSMAT:
- offset += 14;
-
- case ANIMTYPE_DSLAM:
- case ANIMTYPE_DSWOR:
- offset += 7;
- }
-
- return offset;
+ return 14; // XXX: simply include this in indention instead?
}
/* get the appropriate flag(s) for the setting when it is valid */
@@ -1529,14 +1289,14 @@ static void *acf_dstex_setting_ptr(bAnimListElem *ale, int setting, short *type)
}
}
-/* material expander type define */
+/* texture expander type define */
static bAnimChannelType ACF_DSTEX=
{
"Texture Data Expander", /* type name */
- acf_generic_channel_color, /* backdrop color */
- acf_generic_channel_backdrop, /* backdrop */
- acf_generic_indention_0, /* indent level */
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop,/* backdrop */
+ acf_generic_indention_1, /* indent level */
acf_dstex_offset, /* offset */
acf_generic_idblock_name, /* name */
@@ -2097,6 +1857,17 @@ static int acf_dsntree_icon(bAnimListElem *UNUSED(ale))
return ICON_NODETREE;
}
+/* offset for nodetree expanders */
+static short acf_dsntree_offset(bAnimContext *ac, bAnimListElem *ale)
+{
+ bNodeTree *ntree = (bNodeTree *)ale->data;
+ short offset= acf_generic_basic_offset(ac, ale);
+
+ offset += acf_nodetree_rootType_offset(ntree);
+
+ return offset;
+}
+
/* get the appropriate flag(s) for the setting when it is valid */
static int acf_dsntree_setting_flag(bAnimContext *UNUSED(ac), int setting, short *neg)
{
@@ -2154,8 +1925,8 @@ static bAnimChannelType ACF_DSNTREE=
acf_generic_dataexpand_color, /* backdrop color */
acf_generic_dataexpand_backdrop,/* backdrop */
- acf_generic_indention_1, /* indent level */ // XXX this only works for compositing
- acf_generic_basic_offset, /* offset */
+ acf_generic_indention_1, /* indent level */
+ acf_dsntree_offset, /* offset */
acf_generic_idblock_name, /* name */
acf_dsntree_icon, /* icon */
@@ -2564,7 +2335,7 @@ static bAnimChannelType *animchannelTypeInfo[ANIMTYPE_NUM_TYPES];
static short ACF_INIT= 1; /* when non-zero, the list needs to be updated */
/* Initialise type info definitions */
-void ANIM_init_channel_typeinfo_data (void)
+static void ANIM_init_channel_typeinfo_data (void)
{
int type= 0;
@@ -2585,9 +2356,6 @@ void ANIM_init_channel_typeinfo_data (void)
animchannelTypeInfo[type++]= &ACF_FILLACTD; /* Object Action Expander */
animchannelTypeInfo[type++]= &ACF_FILLDRIVERS; /* Drivers Expander */
- animchannelTypeInfo[type++]= &ACF_FILLMATD; /* Materials Expander */
- animchannelTypeInfo[type++]= &ACF_FILLPARTD; /* Particles Expander */
- animchannelTypeInfo[type++]= &ACF_FILLTEXD; /* Textures Expander */
animchannelTypeInfo[type++]= &ACF_DSMAT; /* Material Channel */
animchannelTypeInfo[type++]= &ACF_DSLAM; /* Lamp Channel */
@@ -2855,7 +2623,7 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
*/
- if (ac->sa) {
+ if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
/* for F-Curves, draw color-preview of curve behind checkbox */
if (ale->type == ANIMTYPE_FCURVE) {
@@ -2887,6 +2655,7 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float
char name[ANIM_CHAN_NAME_SIZE]; /* hopefully this will be enough! */
/* set text color */
+ // XXX: if active, highlight differently?
if (selected)
UI_ThemeColor(TH_TEXT_HI);
else
@@ -2925,17 +2694,17 @@ void ANIM_channel_draw (bAnimContext *ac, bAnimListElem *ale, float yminc, float
glColor3fv(color);
/* check if we need to show the sliders */
- if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
+ if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
switch (ac->spacetype) {
case SPACE_ACTION:
{
- SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+ SpaceAction *saction= (SpaceAction *)ac->sl;
draw_sliders= (saction->flag & SACTION_SLIDERS);
}
break;
case SPACE_IPO:
{
- SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
+ SpaceIpo *sipo= (SpaceIpo *)ac->sl;
draw_sliders= (sipo->flag & SIPO_SLIDERS);
}
break;
@@ -3008,11 +2777,8 @@ static void achannel_setting_flush_widget_cb(bContext *C, void *ale_npoin, void
else
return;
- /* get all channels that can possibly be chosen
- * - therefore, the filter is simply ANIMFILTER_CHANNELS, since if we took VISIBLE too,
- * then the channels under closed expanders get ignored...
- */
- filter= ANIMFILTER_CHANNELS;
+ /* get all channels that can possibly be chosen - but ignore hierarchy */
+ filter= ANIMFILTER_DATA_VISIBLE|ANIMFILTER_LIST_CHANNELS;
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* call API method to flush the setting */
@@ -3122,9 +2888,9 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
/* get the base icon for the setting */
switch (setting) {
- case ACHANNEL_SETTING_VISIBLE: /* visibility checkboxes */
- //icon= ((enabled)? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT);
- icon= ICON_CHECKBOX_DEHLT;
+ case ACHANNEL_SETTING_VISIBLE: /* visibility eyes */
+ //icon= ((enabled)? ICON_VISIBLE_IPO_ON : ICON_VISIBLE_IPO_OFF);
+ icon= ICON_VISIBLE_IPO_OFF;
if (ale->type == ANIMTYPE_FCURVE)
tooltip= "Channel is visible in Graph Editor for editing.";
@@ -3153,7 +2919,7 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
tooltip= "Editability of keyframes for this channel.";
break;
- case ACHANNEL_SETTING_MUTE: /* muted eye */
+ case ACHANNEL_SETTING_MUTE: /* muted speaker */
//icon= ((enabled)? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
icon= ICON_MUTE_IPO_OFF;
@@ -3219,7 +2985,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
{
bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
View2D *v2d= &ac->ar->v2d;
- float y, ymid, ytext;
+ float y, ymid /*, ytext*/;
short offset;
/* sanity checks - don't draw anything */
@@ -3238,7 +3004,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
y= (ymaxc - yminc)/2 + yminc;
ymid= y - 7;
/* y-coordinates for text is only 4 down from middle */
- ytext= y - 4;
+ /* ytext= y - 4; */
/* no button backdrop behind icons */
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -3259,7 +3025,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
* - in Graph Editor, checkboxes for visibility in curves area
* - in NLA Editor, glowing dots for solo/not solo...
*/
- if (ac->sa) {
+ if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) && acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE)) {
/* visibility toggle */
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_VISIBLE);
@@ -3270,6 +3036,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
draw_setting_widget(ac, ale, acf, block, offset, ymid, ACHANNEL_SETTING_SOLO);
offset += ICON_WIDTH;
}
+ (void)offset;
}
/* step 4) draw text... */
@@ -3285,17 +3052,17 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
short draw_sliders = 0;
/* check if we need to show the sliders */
- if ((ac->sa) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
+ if ((ac->sl) && ELEM(ac->spacetype, SPACE_ACTION, SPACE_IPO)) {
switch (ac->spacetype) {
case SPACE_ACTION:
{
- SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+ SpaceAction *saction= (SpaceAction *)ac->sl;
draw_sliders= (saction->flag & SACTION_SLIDERS);
}
break;
case SPACE_IPO:
{
- SpaceIpo *sipo= (SpaceIpo *)ac->sa->spacedata.first;
+ SpaceIpo *sipo= (SpaceIpo *)ac->sl;
draw_sliders= (sipo->flag & SIPO_SLIDERS);
}
break;
@@ -3364,7 +3131,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
uiBut *but;
/* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
- but= uiDefAutoButR(block, &ptr, prop, array_index, "", ICON_NULL, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
+ but= uiDefAutoButR(block, &ptr, prop, array_index, "", ICON_NONE, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
/* assign keyframing function according to slider type */
if (ale->type == ANIMTYPE_SHAPEKEY)
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index c5d32492f87..eee7fb0badd 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -25,6 +25,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_channels_edit.c
+ * \ingroup edanimation
+ */
+
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,7 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-
+#include "BKE_library.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -46,6 +51,7 @@
#include "BKE_action.h"
#include "BKE_fcurve.h"
+#include "BKE_gpencil.h"
#include "BKE_context.h"
#include "BKE_global.h"
@@ -164,9 +170,9 @@ void ANIM_set_active_channel (bAnimContext *ac, void *data, short datatype, int
case ANIMTYPE_DSLAT:
{
/* need to verify that this data is valid for now */
- // XXX: ale may be null!
- if (ale->adt)
+ if (ale && ale->adt) {
ale->adt->flag |= ADT_UI_ACTIVE;
+ }
}
break;
}
@@ -189,7 +195,8 @@ void ANIM_deselect_anim_channels (bAnimContext *ac, void *data, short datatype,
int filter;
/* filter data */
- filter= ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS;
+ /* NOTE: no list visible, otherwise, we get dangling */
+ filter= ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
ANIM_animdata_filter(ac, &anim_data, filter, data, datatype);
/* See if we should be selecting or deselecting */
@@ -510,12 +517,34 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *
* - Drivers
* - TODO... some others?
*/
- if (fcu->grp)
- action_groups_remove_channel(adt->action, fcu);
- else if ((ac) && (ac->datatype == ANIMCONT_DRIVERS))
+ if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) {
+ /* driver F-Curve */
BLI_remlink(&adt->drivers, fcu);
- else if (adt->action)
- BLI_remlink(&adt->action->curves, fcu);
+ }
+ else if (adt->action) {
+ /* remove from group or action, whichever one "owns" the F-Curve */
+ if (fcu->grp)
+ action_groups_remove_channel(adt->action, fcu);
+ else
+ BLI_remlink(&adt->action->curves, fcu);
+
+ /* if action has no more F-Curves as a result of this, unlink it from
+ * AnimData if it did not come from a NLA Strip being tweaked.
+ *
+ * This is done so that we don't have dangling Object+Action entries in
+ * channel list that are empty, and linger around long after the data they
+ * are for has disappeared (and probably won't come back).
+ */
+ // XXX: does everybody always want this?
+ /* XXX: there's a problem where many actions could build up in the file if multiple
+ * full add/delete cycles are performed on the same objects, but assume that this is rare
+ */
+ if ((adt->action->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON)==0)
+ {
+ id_us_min(&adt->action->id);
+ adt->action = NULL;
+ }
+ }
/* free the F-Curve itself */
free_fcurve(fcu);
@@ -527,7 +556,7 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *
/* ****************** Operator Utilities ********************************** */
/* poll callback for being in an Animation Editor channels list region */
-int animedit_poll_channels_active (bContext *C)
+static int animedit_poll_channels_active (bContext *C)
{
ScrArea *sa= CTX_wm_area(C);
@@ -543,7 +572,7 @@ int animedit_poll_channels_active (bContext *C)
}
/* poll callback for Animation Editor channels list region + not in NLA-tweakmode for NLA */
-int animedit_poll_channels_nla_tweakmode_off (bContext *C)
+static int animedit_poll_channels_nla_tweakmode_off (bContext *C)
{
ScrArea *sa= CTX_wm_area(C);
Scene *scene = CTX_data_scene(C);
@@ -577,7 +606,7 @@ enum {
};
/* defines for rearranging channels */
-EnumPropertyItem prop_animchannel_rearrange_types[] = {
+static EnumPropertyItem prop_animchannel_rearrange_types[] = {
{REARRANGE_ANIMCHAN_TOP, "TOP", 0, "To Top", ""},
{REARRANGE_ANIMCHAN_UP, "UP", 0, "Up", ""},
{REARRANGE_ANIMCHAN_DOWN, "DOWN", 0, "Down", ""},
@@ -585,57 +614,46 @@ EnumPropertyItem prop_animchannel_rearrange_types[] = {
{0, NULL, 0, NULL, NULL}
};
-/* Rearrange Utilities --------------------------------------------- */
+/* Reordering "Islands" Defines ----------------------------------- */
-/* checks if a channel should be considered for moving */
-static short rearrange_animchannel_is_ok (Link *channel, short type)
-{
- if (type == ANIMTYPE_GROUP) {
- bActionGroup *agrp= (bActionGroup *)channel;
-
- if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED))
- return 1;
- }
- else if (type == ANIMTYPE_FCURVE) {
- FCurve *fcu= (FCurve *)channel;
-
- // FIXME: F-Curve visibility is difficult... needs special filtering tests these days...
- if (SEL_FCU(fcu) && !(fcu->flag & FCURVE_TAGGED))
- return 1;
- }
- else if (type == ANIMTYPE_NLATRACK) {
- NlaTrack *nlt = (NlaTrack *)channel;
-
- if (SEL_NLT(nlt) && !(nlt->flag & NLASTRIP_FLAG_EDIT_TOUCHED))
- return 1;
- }
+/* Island definition - just a listbase container */
+typedef struct tReorderChannelIsland {
+ struct tReorderChannelIsland *next, *prev;
- return 0;
-}
+ ListBase channels; /* channels within this region with the same state */
+ int flag; /* eReorderIslandFlag */
+} tReorderChannelIsland;
+
+/* flags for channel reordering islands */
+typedef enum eReorderIslandFlag {
+ REORDER_ISLAND_SELECTED = (1<<0), /* island is selected */
+ REORDER_ISLAND_UNTOUCHABLE = (1<<1), /* island should be ignored */
+ REORDER_ISLAND_MOVED = (1<<2) /* island has already been moved */
+} eReorderIslandFlag;
-/* checks if another channel can be placed after the given one */
-static short rearrange_animchannel_after_ok (Link *channel, short type)
+
+/* Rearrange Methods --------------------------------------------- */
+
+static short rearrange_island_ok (tReorderChannelIsland *island)
{
- if (type == ANIMTYPE_GROUP) {
- bActionGroup *agrp= (bActionGroup *)channel;
-
- if (agrp->flag & AGRP_TEMP)
- return 0;
- }
+ /* island must not be untouchable */
+ if (island->flag & REORDER_ISLAND_UNTOUCHABLE)
+ return 0;
- return 1;
+ /* island should be selected to be moved */
+ return (island->flag & REORDER_ISLAND_SELECTED) && !(island->flag & REORDER_ISLAND_MOVED);
}
-/* Rearrange Methods --------------------------------------------- */
+/* ............................. */
-static short rearrange_animchannel_top (ListBase *list, Link *channel, short type)
+static short rearrange_island_top (ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_animchannel_is_ok(channel, type)) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
+ if (rearrange_island_ok(island)) {
+ /* remove from current position */
+ BLI_remlink(list, island);
/* make it first element */
- BLI_insertlinkbefore(list, list->first, channel);
+ BLI_insertlinkbefore(list, list->first, island);
return 1;
}
@@ -643,17 +661,18 @@ static short rearrange_animchannel_top (ListBase *list, Link *channel, short typ
return 0;
}
-static short rearrange_animchannel_up (ListBase *list, Link *channel, short type)
+static short rearrange_island_up (ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_animchannel_is_ok(channel, type)) {
- Link *prev= channel->prev;
+ if (rearrange_island_ok(island)) {
+ /* moving up = moving before the previous island, otherwise we're in the same place */
+ tReorderChannelIsland *prev= island->prev;
if (prev) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
+ /* remove from current position */
+ BLI_remlink(list, island);
/* push it up */
- BLI_insertlinkbefore(list, prev, channel);
+ BLI_insertlinkbefore(list, prev, island);
return 1;
}
@@ -662,110 +681,200 @@ static short rearrange_animchannel_up (ListBase *list, Link *channel, short type
return 0;
}
-static short rearrange_animchannel_down (ListBase *list, Link *channel, short type)
+static short rearrange_island_down (ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_animchannel_is_ok(channel, type)) {
- Link *next = (channel->next) ? channel->next->next : NULL;
+ if (rearrange_island_ok(island)) {
+ /* moving down = moving after the next island, otherwise we're in the same place */
+ tReorderChannelIsland *next = island->next;
if (next) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* move it down */
- BLI_insertlinkbefore(list, next, channel);
-
- return 1;
- }
- else if (rearrange_animchannel_after_ok(list->last, type)) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* add at end */
- BLI_addtail(list, channel);
-
- return 1;
- }
- else {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* add just before end */
- BLI_insertlinkbefore(list, list->last, channel);
-
- return 1;
+ /* can only move past if next is not untouchable (i.e. nothing can go after it) */
+ if ((next->flag & REORDER_ISLAND_UNTOUCHABLE)==0) {
+ /* remove from current position */
+ BLI_remlink(list, island);
+
+ /* push it down */
+ BLI_insertlinkafter(list, next, island);
+
+ return 1;
+ }
}
+ /* else: no next channel, so we're at the bottom already, so can't move */
}
return 0;
}
-static short rearrange_animchannel_bottom (ListBase *list, Link *channel, short type)
+static short rearrange_island_bottom (ListBase *list, tReorderChannelIsland *island)
{
- if (rearrange_animchannel_is_ok(channel, type)) {
- if (rearrange_animchannel_after_ok(list->last, type)) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* add at end */
- BLI_addtail(list, channel);
+ if (rearrange_island_ok(island)) {
+ tReorderChannelIsland *last = list->last;
+
+ /* remove island from current position */
+ BLI_remlink(list, island);
+
+ /* add before or after the last channel? */
+ if ((last->flag & REORDER_ISLAND_UNTOUCHABLE)==0) {
+ /* can add after it */
+ BLI_addtail(list, island);
+ }
+ else {
+ /* can at most go just before it, since last cannot be moved */
+ BLI_insertlinkbefore(list, last, island);
- return 1;
}
+
+ return 1;
}
return 0;
}
-/* Generic Stuff ---------------------------------------------------------- */
+/* ............................. */
/* typedef for channel rearranging function
* < list: list that channels belong to
- * < channel: channel to be moved
- * < type: type of channel (eAnim_ChannelType)
+ * < island: island to be moved
* > return[0]: whether operation was a success
*/
-typedef short (*AnimChanRearrangeFp)(ListBase *list, Link *channel, short type);
+typedef short (*AnimChanRearrangeFp)(ListBase *list, tReorderChannelIsland *island);
/* get rearranging function, given 'rearrange' mode */
static AnimChanRearrangeFp rearrange_get_mode_func (short mode)
{
switch (mode) {
case REARRANGE_ANIMCHAN_TOP:
- return rearrange_animchannel_top;
+ return rearrange_island_top;
case REARRANGE_ANIMCHAN_UP:
- return rearrange_animchannel_up;
+ return rearrange_island_up;
case REARRANGE_ANIMCHAN_DOWN:
- return rearrange_animchannel_down;
+ return rearrange_island_down;
case REARRANGE_ANIMCHAN_BOTTOM:
- return rearrange_animchannel_bottom;
+ return rearrange_island_bottom;
default:
return NULL;
}
}
-/* ........ */
-
-/* These iteration helpers (ideally should be inlined, but probably not necessary) */
+/* Rearrange Islands Generics ------------------------------------- */
-static Link *rearrange_iter_first (ListBase *list, short mode)
+/* add channel into list of islands */
+static void rearrange_animchannel_add_to_islands (ListBase *islands, ListBase *srcList, Link *channel, short type)
{
- return (mode > 0) ? list->first : list->last;
+ tReorderChannelIsland *island = islands->last; /* always try to add to last island if possible */
+ short is_sel=0, is_untouchable=0;
+
+ /* get flags - selected and untouchable from the channel */
+ switch (type) {
+ case ANIMTYPE_GROUP:
+ {
+ bActionGroup *agrp= (bActionGroup *)channel;
+
+ is_sel= SEL_AGRP(agrp);
+ is_untouchable= (agrp->flag & AGRP_TEMP) != 0;
+ }
+ break;
+ case ANIMTYPE_FCURVE:
+ {
+ FCurve *fcu= (FCurve *)channel;
+
+ is_sel= SEL_FCU(fcu);
+ }
+ break;
+ case ANIMTYPE_NLATRACK:
+ {
+ NlaTrack *nlt= (NlaTrack *)channel;
+
+ is_sel= SEL_NLT(nlt);
+ }
+ break;
+
+ default:
+ printf("rearrange_animchannel_add_to_islands(): don't know how to handle channels of type %d\n", type);
+ return;
+ }
+
+ /* do we need to add to a new island? */
+ if ((island == NULL) || /* 1) no islands yet */
+ ((island->flag & REORDER_ISLAND_SELECTED) == 0) || /* 2) unselected islands have single channels only - to allow up/down movement */
+ (is_sel == 0)) /* 3) if channel is unselected, stop existing island (it was either wrong sel status, or full already) */
+ {
+ /* create a new island now */
+ island = MEM_callocN(sizeof(tReorderChannelIsland), "tReorderChannelIsland");
+ BLI_addtail(islands, island);
+
+ if (is_sel)
+ island->flag |= REORDER_ISLAND_SELECTED;
+ if (is_untouchable)
+ island->flag |= REORDER_ISLAND_UNTOUCHABLE;
+ }
+
+ /* add channel to island - need to remove it from its existing list first though */
+ BLI_remlink(srcList, channel);
+ BLI_addtail(&island->channels, channel);
}
-static Link *rearrange_iter_next (Link *item, short mode)
+/* flatten islands out into a single list again */
+static void rearrange_animchannel_flatten_islands (ListBase *islands, ListBase *srcList)
{
- return (mode > 0) ? item->next : item->prev;
+ tReorderChannelIsland *island, *isn=NULL;
+
+ /* make sure srcList is empty now */
+ BLI_assert(srcList->first == NULL);
+
+ /* go through merging islands */
+ for (island = islands->first; island; island = isn) {
+ isn = island->next;
+
+ /* merge island channels back to main list, then delete the island */
+ BLI_movelisttolist(srcList, &island->channels);
+ BLI_freelinkN(islands, island);
+ }
}
-/* ........ */
+/* ............................. */
-/* Clear 'tag' on all F-Curves */
-static void rearrange_clear_fcurve_tags (ListBase *list)
+/* performing rearranging of channels using islands */
+static short rearrange_animchannel_islands (ListBase *list, AnimChanRearrangeFp rearrange_func, short mode, short type)
{
- FCurve *fcu;
+ ListBase islands = {NULL, NULL};
+ Link *channel, *chanNext=NULL;
+ short done = 0;
- for (fcu = list->first; fcu; fcu = fcu->next)
- fcu->flag &= ~FCURVE_TAGGED;
+ /* don't waste effort on an empty list */
+ if (list->first == NULL)
+ return 0;
+
+ /* group channels into islands */
+ for (channel = list->first; channel; channel = chanNext) {
+ chanNext = channel->next;
+ rearrange_animchannel_add_to_islands(&islands, list, channel, type);
+ }
+
+ /* perform moving of selected islands now, but only if there is more than one of 'em so that something will happen
+ * - scanning of the list is performed in the opposite direction to the direction we're moving things, so that we
+ * shouldn't need to encounter items we've moved already
+ */
+ if (islands.first != islands.last) {
+ tReorderChannelIsland *first = (mode > 0) ? islands.last : islands.first;
+ tReorderChannelIsland *island, *isn=NULL;
+
+ for (island = first; island; island = isn) {
+ isn = (mode > 0) ? island->prev : island->next;
+
+ /* perform rearranging */
+ if (rearrange_func(&islands, island)) {
+ island->flag |= REORDER_ISLAND_MOVED;
+ done = 1;
+ }
+ }
+ }
+
+ /* ungroup islands */
+ rearrange_animchannel_flatten_islands(&islands, list);
+
+ /* did we do anything? */
+ return done;
}
/* NLA Specific Stuff ----------------------------------------------------- */
@@ -776,8 +885,6 @@ static void rearrange_clear_fcurve_tags (ListBase *list)
*/
static void rearrange_nla_channels (bAnimContext *UNUSED(ac), AnimData *adt, short mode)
{
- NlaTrack *nlt, *track;
-
AnimChanRearrangeFp rearrange_func;
/* hack: invert mode so that functions will work in right order */
@@ -792,23 +899,8 @@ static void rearrange_nla_channels (bAnimContext *UNUSED(ac), AnimData *adt, sho
//if (EXPANDED_DRVD(adt) == 0)
// return;
- /* clear "moved" flag from all tracks */
- for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
- nlt->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED;
-
- /* reorder all selected tracks */
- for (nlt= (NlaTrack *)rearrange_iter_first(&adt->nla_tracks, mode); nlt; nlt= track) {
- /* Get next channel to consider */
- track= (NlaTrack *)rearrange_iter_next((Link *)nlt, mode);
-
- /* Try to do channel */
- if (rearrange_func(&adt->nla_tracks, (Link *)nlt, ANIMTYPE_NLATRACK))
- nlt->flag |= NLASTRIP_FLAG_EDIT_TOUCHED;
- }
-
- /* clear "moved" flag from all tracks */
- for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
- nlt->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED;
+ /* perform rearranging on tracks list */
+ rearrange_animchannel_islands(&adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK);
}
/* Drivers Specific Stuff ------------------------------------------------- */
@@ -818,8 +910,6 @@ static void rearrange_nla_channels (bAnimContext *UNUSED(ac), AnimData *adt, sho
*/
static void rearrange_driver_channels (bAnimContext *UNUSED(ac), AnimData *adt, short mode)
{
- FCurve *fcu, *fcun;
-
/* get rearranging function */
AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
@@ -830,19 +920,8 @@ static void rearrange_driver_channels (bAnimContext *UNUSED(ac), AnimData *adt,
if (EXPANDED_DRVD(adt) == 0)
return;
- rearrange_clear_fcurve_tags(&adt->drivers);
-
- /* reorder all selected driver F-Curves */
- for (fcu= (FCurve *)rearrange_iter_first(&adt->drivers, mode); fcu; fcu= fcun) {
- /* Get next channel to consider */
- fcun= (FCurve *)rearrange_iter_next((Link *)fcu, mode);
-
- /* Try to do channel */
- if (rearrange_func(&adt->drivers, (Link *)fcu, ANIMTYPE_FCURVE))
- fcu->flag |= FCURVE_TAGGED;
- }
-
- rearrange_clear_fcurve_tags(&adt->drivers);
+ /* perform rearranging on drivers list (drivers are really just F-Curves) */
+ rearrange_animchannel_islands(&adt->drivers, rearrange_func, mode, ANIMTYPE_FCURVE);
}
/* Action Specific Stuff ------------------------------------------------- */
@@ -856,9 +935,6 @@ static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
if (act == NULL)
return;
- /* clear "moved" flag from all FCurves */
- rearrange_clear_fcurve_tags(&act->curves);
-
/* Separate F-Curves into lists per group */
for (agrp= act->groups.first; agrp; agrp= agrp->next) {
if (agrp->channels.first) {
@@ -919,9 +995,6 @@ static void join_groups_action_temp (bAction *act)
break;
}
}
-
- /* clear "moved" flag from all fcurve's */
- rearrange_clear_fcurve_tags(&act->curves);
}
/* Change the order of anim-channels within action
@@ -929,10 +1002,8 @@ static void join_groups_action_temp (bAction *act)
*/
static void rearrange_action_channels (bAnimContext *ac, bAction *act, short mode)
{
- bActionGroup *agrp, *grp;
bActionGroup tgrp;
- FCurve *fcu, *fcun;
- short do_channels = 1;
+ short do_channels;
/* get rearranging function */
AnimChanRearrangeFp rearrange_func = rearrange_get_mode_func(mode);
@@ -940,36 +1011,22 @@ static void rearrange_action_channels (bAnimContext *ac, bAction *act, short mod
if (rearrange_func == NULL)
return;
- /* make sure we're only operating with groups */
+ /* make sure we're only operating with groups (vs a mixture of groups+curves) */
split_groups_action_temp(act, &tgrp);
- /* rearrange groups first (and then, only consider channels if the groups weren't moved) */
- for (agrp= (bActionGroup *)rearrange_iter_first(&act->groups, mode); agrp; agrp= grp) {
- /* Get next group to consider */
- grp= (bActionGroup *)rearrange_iter_next((Link *)agrp, mode);
-
- /* try to do group first */
- if (rearrange_func(&act->groups, (Link *)agrp, ANIMTYPE_GROUP)) {
- do_channels= 0;
- agrp->flag |= AGRP_MOVED;
- }
- }
+ /* rearrange groups first
+ * - the group's channels will only get considered if nothing happened when rearranging the groups
+ * i.e. the rearrange function returned 0
+ */
+ do_channels = rearrange_animchannel_islands(&act->groups, rearrange_func, mode, ANIMTYPE_GROUP) == 0;
if (do_channels) {
- for (agrp= (bActionGroup *)rearrange_iter_first(&act->groups, mode); agrp; agrp= grp) {
- /* Get next group to consider */
- grp= (bActionGroup *)rearrange_iter_next((Link *)agrp, mode);
-
+ bActionGroup *agrp;
+
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
/* only consider F-Curves if they're visible (group expanded) */
- if (EXPANDED_AGRP(agrp)) {
- for (fcu= (FCurve *)rearrange_iter_first(&agrp->channels, mode); fcu; fcu= fcun) {
- /* Get next channel to consider */
- fcun= (FCurve *)rearrange_iter_next((Link *)fcu, mode);
-
- /* Try to do channel */
- if (rearrange_func(&agrp->channels, (Link *)fcu, ANIMTYPE_FCURVE))
- fcu->flag |= FCURVE_TAGGED;
- }
+ if (EXPANDED_AGRP(ac, agrp)) {
+ rearrange_animchannel_islands(&agrp->channels, rearrange_func, mode, ANIMTYPE_FCURVE);
}
}
}
@@ -998,7 +1055,8 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
mode= RNA_enum_get(op->ptr, "direction");
/* get animdata blocks */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_ANIMDATA);
+ // XXX: hierarchy visibility is provisional atm... might be wrong decision!
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -1024,7 +1082,7 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
// FIXME: actions should only be considered once!
if (adt->action)
rearrange_action_channels(&ac, adt->action, mode);
- else
+ else if (G.f & G_DEBUG)
printf("animdata has no action\n");
break;
}
@@ -1039,7 +1097,7 @@ static int animchannels_rearrange_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_move (wmOperatorType *ot)
+static void ANIM_OT_channels_move (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Move Channels";
@@ -1054,7 +1112,7 @@ void ANIM_OT_channels_move (wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* props */
- RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
+ ot->prop= RNA_def_enum(ot->srna, "direction", prop_animchannel_rearrange_types, REARRANGE_ANIMCHAN_DOWN, "Direction", "");
}
/* ******************** Delete Channel Operator *********************** */
@@ -1078,7 +1136,7 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* do groups only first (unless in Drivers mode, where there are none) */
if (ac.datatype != ANIMCONT_DRIVERS) {
/* filter data */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* delete selected groups and their associated channels */
@@ -1114,35 +1172,48 @@ static int animchannels_delete_exec(bContext *C, wmOperator *UNUSED(op))
BLI_freelistN(&anim_data);
}
- /* now do F-Curves */
- if (ac.datatype != ANIMCONT_GPENCIL) {
- /* filter data */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* delete selected F-Curves */
- for (ale= anim_data.first; ale; ale= ale->next) {
- /* only F-Curves, and only if we can identify its parent */
- if (ale->type == ANIMTYPE_FCURVE) {
+ /* filter data */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* delete selected data channels */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ switch (ale->type) {
+ case ANIMTYPE_FCURVE:
+ {
+ /* F-Curves if we can identify its parent */
AnimData *adt= ale->adt;
FCurve *fcu= (FCurve *)ale->data;
/* try to free F-Curve */
ANIM_fcurve_delete_from_animdata(&ac, adt, fcu);
}
+ break;
+
+ case ANIMTYPE_GPLAYER:
+ {
+ /* Grease Pencil layer */
+ bGPdata *gpd= (bGPdata *)ale->id;
+ bGPDlayer *gpl= (bGPDlayer *)ale->data;
+
+ /* try to delete the layer's data and the layer itself */
+ free_gpencil_frames(gpl);
+ BLI_freelinkN(&gpd->layers, gpl);
+ }
+ break;
}
-
- /* cleanup */
- BLI_freelistN(&anim_data);
}
+ /* cleanup */
+ BLI_freelistN(&anim_data);
+
/* send notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN|NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_delete (wmOperatorType *ot)
+static void ANIM_OT_channels_delete (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Delete Channels";
@@ -1172,12 +1243,27 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- /* get list of all channels that selection may need to be flushed to */
- filter= ANIMFILTER_CHANNELS;
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy mustn't affect what we have access to here...
+ */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
-
- /* hide all channels not selected */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_NODUPLIS);
+
+ /* hide all channels not selected
+ * - hierarchy matters if we're doing this from the channels region
+ * since we only want to apply this to channels we can "see",
+ * and have these affect their relatives
+ * - but for Graph Editor, this gets used also from main region
+ * where hierarchy doesn't apply, as for [#21276]
+ */
+ if ((ac.spacetype == SPACE_IPO) && (ac.regiontype != RGN_TYPE_CHANNELS)) {
+ /* graph editor (case 2) */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ }
+ else {
+ /* standard case */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_UNSEL | ANIMFILTER_NODUPLIS);
+ }
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
for (ale= anim_data.first; ale; ale= ale->next) {
@@ -1219,7 +1305,7 @@ static int animchannels_visibility_set_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_visibility_set (wmOperatorType *ot)
+static void ANIM_OT_channels_visibility_set (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Set Visibility";
@@ -1251,12 +1337,16 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
if (ANIM_animdata_get_context(C, &ac) == 0)
return OPERATOR_CANCELLED;
- /* get list of all channels that selection may need to be flushed to */
- filter= (ANIMFILTER_CHANNELS | ANIMFILTER_NODUPLIS);
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy mustn't affect what we have access to here...
+ */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype);
- /* filter data */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
+ /* filter data
+ * - restrict this to only applying on settings we can get to in the list
+ */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* See if we should be making showing all selected or hiding */
@@ -1292,7 +1382,7 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *UNUSED(o
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Toggle Visibility";
@@ -1310,7 +1400,7 @@ void ANIM_OT_channels_visibility_toggle (wmOperatorType *ot)
/* ********************** Set Flags Operator *********************** */
/* defines for setting animation-channel flags */
-EnumPropertyItem prop_animchannel_setflag_types[] = {
+static EnumPropertyItem prop_animchannel_setflag_types[] = {
{ACHANNEL_SETFLAG_TOGGLE, "TOGGLE", 0, "Toggle", ""},
{ACHANNEL_SETFLAG_CLEAR, "DISABLE", 0, "Disable", ""},
{ACHANNEL_SETFLAG_ADD, "ENABLE", 0, "Enable", ""},
@@ -1320,7 +1410,7 @@ EnumPropertyItem prop_animchannel_setflag_types[] = {
/* defines for set animation-channel settings */
// TODO: could add some more types, but those are really quite dependent on the mode...
-EnumPropertyItem prop_animchannel_settings_types[] = {
+static EnumPropertyItem prop_animchannel_settings_types[] = {
{ACHANNEL_SETTING_PROTECT, "PROTECT", 0, "Protect", ""},
{ACHANNEL_SETTING_MUTE, "MUTE", 0, "Mute", ""},
{0, NULL, 0, NULL, NULL}
@@ -1329,10 +1419,6 @@ EnumPropertyItem prop_animchannel_settings_types[] = {
/* ------------------- */
-/* macro to be used in setflag_anim_channels */
-#define ASUBCHANNEL_SEL_OK(ale) ( (onlysel == 0) || \
- ((ale->id) && (GS(ale->id->name)==ID_OB) && (((Object *)ale->id)->flag & SELECT)) )
-
/* Set/clear a particular flag (setting) for all selected + visible channels
* setting: the setting to modify
* mode: eAnimChannels_SetFlag
@@ -1348,14 +1434,29 @@ static void setflag_anim_channels (bAnimContext *ac, short setting, short mode,
/* filter data that we need if flush is on */
if (flush) {
- /* get list of all channels that selection may need to be flushed to */
- filter= ANIMFILTER_CHANNELS;
+ /* get list of all channels that selection may need to be flushed to
+ * - hierarchy visibility needs to be ignored so that settings can get flushed
+ * "down" inside closed containers
+ */
+ filter= ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS;
ANIM_animdata_filter(ac, &all_data, filter, ac->data, ac->datatype);
}
- /* filter data that we're working on */
- // XXX: noduplis enabled so that results don't cancel, but will be problematic for some channels where only type differs
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS | ANIMFILTER_NODUPLIS);
+ /* filter data that we're working on
+ * - hierarchy matters if we're doing this from the channels region
+ * since we only want to apply this to channels we can "see",
+ * and have these affect their relatives
+ * - but for Graph Editor, this gets used also from main region
+ * where hierarchy doesn't apply [#21276]
+ */
+ if ((ac->spacetype == SPACE_IPO) && (ac->regiontype != RGN_TYPE_CHANNELS)) {
+ /* graph editor (case 2) */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_NODUPLIS);
+ }
+ else {
+ /* standard case */
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS);
+ }
if (onlysel) filter |= ANIMFILTER_SEL;
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
@@ -1424,7 +1525,7 @@ static int animchannels_setflag_exec(bContext *C, wmOperator *op)
}
-void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Enable Channel Setting";
@@ -1446,7 +1547,7 @@ void ANIM_OT_channels_setting_enable (wmOperatorType *ot)
ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
-void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Disable Channel Setting";
@@ -1468,7 +1569,7 @@ void ANIM_OT_channels_setting_disable (wmOperatorType *ot)
ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
-void ANIM_OT_channels_setting_invert (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_invert (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Invert Channel Setting";
@@ -1490,7 +1591,7 @@ void ANIM_OT_channels_setting_invert (wmOperatorType *ot)
ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
-void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Toggle Channel Setting";
@@ -1512,7 +1613,7 @@ void ANIM_OT_channels_setting_toggle (wmOperatorType *ot)
ot->prop= RNA_def_enum(ot->srna, "type", prop_animchannel_settings_types, 0, "Type", "");
}
-void ANIM_OT_channels_editable_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_editable_toggle (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Toggle Channel Editability";
@@ -1557,7 +1658,7 @@ static int animchannels_expand_exec (bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_expand (wmOperatorType *ot)
+static void ANIM_OT_channels_expand (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Expand Channels";
@@ -1599,7 +1700,7 @@ static int animchannels_collapse_exec (bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_collapse (wmOperatorType *ot)
+static void ANIM_OT_channels_collapse (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Collapse Channels";
@@ -1648,13 +1749,22 @@ static int animchannels_enable_exec (bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* filter data */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS);
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_NODUPLIS);
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* loop through filtered data and clean curves */
for (ale= anim_data.first; ale; ale= ale->next) {
FCurve *fcu = (FCurve *)ale->data;
+
+ /* remove disabled flags from F-Curves */
fcu->flag &= ~FCURVE_DISABLED;
+
+ /* for drivers, let's do the same too */
+ if (fcu->driver)
+ fcu->driver->flag &= ~DRIVER_FLAG_INVALID;
+
+ /* tag everything for updates - in particular, this is needed to get drivers working again */
+ ANIM_list_elem_update(ac.scene, ale);
}
/* free temp data */
@@ -1666,7 +1776,7 @@ static int animchannels_enable_exec (bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_fcurves_enable (wmOperatorType *ot)
+static void ANIM_OT_channels_fcurves_enable (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Revive Disabled F-Curves";
@@ -1703,7 +1813,7 @@ static int animchannels_deselectall_exec (bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot)
+static void ANIM_OT_channels_select_all_toggle (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Select All";
@@ -1729,13 +1839,14 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
bAnimListElem *ale;
int filter;
+ SpaceNla *snla = (SpaceNla *)ac->sl;
View2D *v2d= &ac->ar->v2d;
rctf rectf;
float ymin, ymax;
/* set initial y extents */
if (ac->datatype == ANIMCONT_NLA) {
- ymin = (float)(-NLACHANNEL_HEIGHT);
+ ymin = (float)(-NLACHANNEL_HEIGHT(snla));
ymax = 0.0f;
}
else {
@@ -1748,13 +1859,13 @@ static void borderselect_anim_channels (bAnimContext *ac, rcti *rect, short sele
UI_view2d_region_to_view(v2d, rect->xmax, rect->ymax-2, &rectf.xmax, &rectf.ymax);
/* filter data */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop over data, doing border select */
for (ale= anim_data.first; ale; ale= ale->next) {
if (ac->datatype == ANIMCONT_NLA)
- ymin= ymax - NLACHANNEL_STEP;
+ ymin= ymax - NLACHANNEL_STEP(snla);
else
ymin= ymax - ACHANNEL_STEP;
@@ -1828,7 +1939,7 @@ static int animchannels_borderselect_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_select_border(wmOperatorType *ot)
+static void ANIM_OT_channels_select_border(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Border Select";
@@ -1839,6 +1950,7 @@ void ANIM_OT_channels_select_border(wmOperatorType *ot)
ot->invoke= WM_border_select_invoke;
ot->exec= animchannels_borderselect_exec;
ot->modal= WM_border_select_modal;
+ ot->cancel= WM_border_select_cancel;
ot->poll= animedit_poll_channels_nla_tweakmode_off;
@@ -1861,7 +1973,7 @@ static int mouse_anim_channels (bAnimContext *ac, float UNUSED(x), int channel_i
/* get the channel that was clicked on */
/* filter channels */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
+ filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* get channel from index */
@@ -2106,7 +2218,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
bAnimContext ac;
ARegion *ar;
View2D *v2d;
- int mval[2], channel_index;
+ int channel_index;
int notifierFlags = 0;
short selectmode;
float x, y;
@@ -2120,10 +2232,6 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
ar= ac.ar;
v2d= &ar->v2d;
- /* get mouse coordinates (in region coordinates) */
- mval[0]= (event->x - ar->winrct.xmin);
- mval[1]= (event->y - ar->winrct.ymin);
-
/* select mode is either replace (deselect all, then add) or add/extend */
if (RNA_boolean_get(op->ptr, "extend"))
selectmode= SELECT_INVERT;
@@ -2137,7 +2245,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
* so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use
* ACHANNEL_HEIGHT_HALF.
*/
- UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
+ UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
/* handle mouse-click in the relevant channel then */
@@ -2149,7 +2257,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *
return OPERATOR_FINISHED;
}
-void ANIM_OT_channels_click (wmOperatorType *ot)
+static void ANIM_OT_channels_click (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Mouse Click on Channels";
diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c
index 340101612b9..13061113926 100644
--- a/source/blender/editors/animation/anim_deps.c
+++ b/source/blender/editors/animation/anim_deps.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_deps.c
+ * \ingroup edanimation
+ */
+
+
#include <string.h>
#include "MEM_guardedalloc.h"
@@ -252,7 +257,7 @@ void ANIM_sync_animchannels_to_data (const bContext *C)
/* filter data */
/* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed */
- filter= ANIMFILTER_CHANNELS;
+ filter= ANIMFILTER_DATA_VISIBLE|ANIMFILTER_LIST_CHANNELS;
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
/* flush settings as appropriate depending on the types of the channels */
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index dd27de883b3..22ab419de2e 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -25,6 +25,11 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
+/** \file blender/editors/animation/anim_draw.c
+ * \ingroup edanimation
+ */
+
#include "BLO_sys_types.h"
#include "DNA_anim_types.h"
@@ -95,7 +100,7 @@ void ANIM_timecode_string_from_frame (char *str, Scene *scene, int power, short
* to cope with 'half' frames, etc., which should be fine in most cases
*/
seconds= (int)cfra;
- frames= (int)floor( ((cfra - seconds) * FPS) + 0.5f );
+ frames= (int)floor( (((double)cfra - (double)seconds) * FPS) + 0.5 );
}
else {
/* seconds (with pixel offset rounding) */
@@ -220,7 +225,10 @@ void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag)
vec[0]= (float)(scene->r.cfra * scene->r.framelen);
UI_ThemeColor(TH_CFRAME);
- glLineWidth(2.0);
+ if (flag & DRAWCFRA_WIDE)
+ glLineWidth(3.0);
+ else
+ glLineWidth(2.0);
glBegin(GL_LINE_STRIP);
vec[1]= v2d->cur.ymin-500.0f; /* XXX arbitrary... want it go to bottom */
@@ -232,19 +240,19 @@ void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag)
/* Draw dark green line if slow-parenting/time-offset is enabled */
if (flag & DRAWCFRA_SHOW_TIMEOFS) {
- Object *ob= (scene->basact) ? (scene->basact->object) : 0;
+ Object *ob= OBACT;
if(ob) {
float timeoffset= give_timeoffset(ob);
// XXX ob->ipoflag is depreceated!
if ((ob->ipoflag & OB_OFFS_OB) && (timeoffset != 0.0f)) {
vec[0]-= timeoffset; /* could avoid calling twice */
-
+
UI_ThemeColorShade(TH_CFRAME, -30);
-
+
glBegin(GL_LINE_STRIP);
/*vec[1]= v2d->cur.ymax;*/ // this is set already. this line is only included
glVertex2fv(vec);
-
+
vec[1]= v2d->cur.ymin;
glVertex2fv(vec);
glEnd();
@@ -352,7 +360,7 @@ static short bezt_nlamapping_apply(KeyframeEditData *ked, BezTriple *bezt)
*/
void ANIM_nla_mapping_apply_fcurve (AnimData *adt, FCurve *fcu, short restore, short only_keys)
{
- KeyframeEditData ked= {{0}};
+ KeyframeEditData ked= {{NULL}};
KeyframeEditFunc map_cb;
/* init edit data
@@ -394,9 +402,9 @@ float ANIM_unit_mapping_get_factor (Scene *scene, ID *id, FCurve *fcu, short res
/* if the radians flag is not set, default to using degrees which need conversions */
if ((scene) && (scene->unit.system_rotation == USER_UNIT_ROT_RADIANS) == 0) {
if (restore)
- return M_PI / 180.0f; /* degrees to radians */
+ return M_PI / 180.0; /* degrees to radians */
else
- return 180.0f / M_PI; /* radians to degrees */
+ return 180.0 / M_PI; /* radians to degrees */
}
}
@@ -465,7 +473,7 @@ void ANIM_unit_mapping_apply_fcurve (Scene *scene, ID *id, FCurve *fcu, short fl
// TODO: only sel?
if (fcu->fpt) {
FPoint *fpt;
- int i;
+ unsigned int i;
for (i=0, fpt=fcu->fpt; i < fcu->totvert; i++, fpt++) {
/* apply unit mapping */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 6d36daa854c..047a7763fd8 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_filter.c
+ * \ingroup edanimation
+ */
+
+
/* This file contains a system used to provide a layer of abstraction between sources
* of animation data and tools in Animation Editors. The method used here involves
* generating a list of edit structures which enable tools to naively perform the actions
@@ -122,6 +127,9 @@ static Key *actedit_get_shapekeys (bAnimContext *ac)
/* Get data being edited in Action Editor (depending on current 'mode') */
static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
{
+ /* get dopesheet */
+ ac->ads = &saction->ads;
+
/* sync settings with current view status, then return appropriate data */
switch (saction->mode) {
case SACTCONT_ACTION: /* 'Action Editor' */
@@ -185,6 +193,7 @@ static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
sipo->ads->source= (ID *)ac->scene;
}
+ ac->ads = sipo->ads;
/* set settings for Graph Editor - "Selected = Editable" */
if (sipo->flag & SIPO_SELCUVERTSONLY)
@@ -233,6 +242,7 @@ static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
/* init dopesheet data if non-existant (i.e. for old files) */
if (snla->ads == NULL)
snla->ads= MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
+ ac->ads = snla->ads;
/* sync settings with current view status, then return appropriate data */
/* update scene-pointer (no need to check for pinning yet, as not implemented) */
@@ -253,29 +263,29 @@ static short nlaedit_get_context (bAnimContext *ac, SpaceNla *snla)
*/
short ANIM_animdata_context_getdata (bAnimContext *ac)
{
- ScrArea *sa= ac->sa;
+ SpaceLink *sl = ac->sl;
short ok= 0;
/* context depends on editor we are currently in */
- if (sa) {
- switch (sa->spacetype) {
+ if (sl) {
+ switch (ac->spacetype) {
case SPACE_ACTION:
{
- SpaceAction *saction= (SpaceAction *)sa->spacedata.first;
+ SpaceAction *saction= (SpaceAction *)sl;
ok= actedit_get_context(ac, saction);
}
break;
case SPACE_IPO:
{
- SpaceIpo *sipo= (SpaceIpo *)sa->spacedata.first;
+ SpaceIpo *sipo= (SpaceIpo *)sl;
ok= graphedit_get_context(ac, sipo);
}
break;
case SPACE_NLA:
{
- SpaceNla *snla= (SpaceNla *)sa->spacedata.first;
+ SpaceNla *snla= (SpaceNla *)sl;
ok= nlaedit_get_context(ac, snla);
}
break;
@@ -298,6 +308,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
{
ScrArea *sa= CTX_wm_area(C);
ARegion *ar= CTX_wm_region(C);
+ SpaceLink *sl= CTX_wm_space_data(C);
Scene *scene= CTX_data_scene(C);
/* clear old context info */
@@ -312,6 +323,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
}
ac->sa= sa;
ac->ar= ar;
+ ac->sl= sl;
ac->spacetype= (sa) ? sa->spacetype : 0;
ac->regiontype= (ar) ? ar->regiontype : 0;
@@ -322,6 +334,35 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* ************************************************************ */
/* Blender Data <-- Filter --> Channels to be operated on */
+/* macros to use before/after getting the sub-channels of some channel,
+ * to abstract away some of the tricky logic involved
+ *
+ * cases:
+ * 1) Graph Edit main area (just data) OR channels visible in Channel List
+ * 2) If not showing channels, we're only interested in the data (Action Editor's editing)
+ * 3) We don't care what data, we just care there is some (so that a collapsed
+ * channel can be kept around). No need to clear channels-flag in order to
+ * keep expander channels with no sub-data out, as those cases should get
+ * dealt with by the recursive detection idiom in place.
+ */
+#define BEGIN_ANIMFILTER_SUBCHANNELS(expanded_check) \
+ { \
+ int _filter = filter_mode; \
+ short _doSubChannels = 0; \
+ if (!(filter_mode & ANIMFILTER_LIST_VISIBLE) || (expanded_check)) \
+ _doSubChannels=1; \
+ else if (!(filter_mode & ANIMFILTER_LIST_CHANNELS)) \
+ _doSubChannels=2; \
+ else {\
+ filter_mode |= ANIMFILTER_TMP_PEEK; \
+ }
+ /* ... standard sub-channel filtering can go on here now ... */
+#define END_ANIMFILTER_SUBCHANNELS \
+ filter_mode = _filter; \
+ }
+
+/* ............................... */
+
/* quick macro to test if AnimData is usable */
#define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
@@ -331,8 +372,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* quick macro to test if AnimData is usable for NLA */
#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
-
-/* Quick macro to test for all three avove usability tests, performing the appropriate provided
+/* Quick macro to test for all three above usability tests, performing the appropriate provided
* action for each when the AnimData context is appropriate.
*
* Priority order for this goes (most important, to least): AnimData blocks, NLA, Drivers, Keyframes.
@@ -342,7 +382,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
* - ListBase anim_data;
* - bDopeSheet *ads;
* - bAnimListElem *ale;
- * - int items;
+ * - size_t items;
*
* - id: ID block which should have an AnimData pointer following it immediately, to use
* - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
@@ -362,7 +402,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
{\
if ((id)->adt) {\
- if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) {\
+ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !((id)->adt->flag & ADT_CURVES_NOT_VISIBLE)) {\
if (filter_mode & ANIMFILTER_ANIMDATA) {\
adtOk\
}\
@@ -388,17 +428,31 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
}\
}
+/* ............................... */
-/* quick macro to add a pointer to an AnimData block as a channel */
-#define ANIMDATA_ADD_ANIMDATA(id) \
- {\
- ale= make_new_animlistelem((id)->adt, ANIMTYPE_ANIMDATA, NULL, ANIMTYPE_NONE, (ID *)id);\
+/* Add a new animation channel, taking into account the "peek" flag, which is used to just check
+ * whether any channels will be added (but without needing them to actually get created).
+ *
+ * ! This causes the calling function to return early if we're only "peeking" for channels
+ */
+// XXX: ale_statement stuff is really a hack for one special case. It shouldn't really be needed...
+#define ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, ale_statement) \
+ if (filter_mode & ANIMFILTER_TMP_PEEK) \
+ return 1; \
+ else { \
+ bAnimListElem *ale= make_new_animlistelem(channel_data, channel_type, (ID *)owner_id); \
if (ale) {\
- BLI_addtail(anim_data, ale);\
- items++;\
- }\
+ BLI_addtail(anim_data, ale); \
+ items++; \
+ ale_statement \
+ } \
}
+#define ANIMCHANNEL_NEW_CHANNEL(channel_data, channel_type, owner_id) \
+ ANIMCHANNEL_NEW_CHANNEL_FULL(channel_data, channel_type, owner_id, {})
+
+/* ............................... */
+
/* quick macro to test if an anim-channel representing an AnimData block is suitably active */
#define ANIMCHANNEL_ACTIVEOK(ale) \
( !(filter_mode & ANIMFILTER_ACTIVE) || !(ale->adt) || (ale->adt->flag & ADT_UI_ACTIVE) )
@@ -427,7 +481,7 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
/* this function allocates memory for a new bAnimListElem struct for the
* provided animation channel-data.
*/
-bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, short ownertype, ID *owner_id)
+static bAnimListElem *make_new_animlistelem (void *data, short datatype, ID *owner_id)
{
bAnimListElem *ale= NULL;
@@ -438,10 +492,6 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
ale->data= data;
ale->type= datatype;
- // XXX what is the point of the owner data?
- // xxx try and use this to simplify the problem of finding whether parent channels are working...
- ale->owner= owner;
- ale->ownertype= ownertype;
ale->id= owner_id;
ale->adt= BKE_animdata_from_id(owner_id);
@@ -504,55 +554,6 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
ale->datatype= ALE_NONE;
}
break;
- case ANIMTYPE_FILLMATD:
- {
- Object *ob= (Object *)data;
-
- ale->flag= FILTER_MAT_OBJC(ob);
-
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- break;
- case ANIMTYPE_FILLPARTD:
- {
- Object *ob= (Object *)data;
-
- ale->flag= FILTER_PART_OBJC(ob);
-
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- break;
- case ANIMTYPE_FILLTEXD:
- {
- ID *id= (ID *)data;
-
- switch (GS(id->name)) {
- case ID_MA:
- {
- Material *ma= (Material *)id;
- ale->flag= FILTER_TEX_MATC(ma);
- }
- break;
- case ID_LA:
- {
- Lamp *la= (Lamp *)id;
- ale->flag= FILTER_TEX_LAMC(la);
- }
- break;
- case ID_WO:
- {
- World *wo= (World *)id;
- ale->flag= FILTER_TEX_WORC(wo);
- }
- break;
- }
-
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- break;
case ANIMTYPE_DSMAT:
{
@@ -676,7 +677,7 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
bNodeTree *ntree= (bNodeTree *)data;
AnimData *adt= ntree->adt;
- ale->flag= FILTER_NTREE_SCED(ntree);
+ ale->flag= FILTER_NTREE_DATA(ntree);
ale->key_data= (adt) ? adt->action : NULL;
ale->datatype= ALE_ACT;
@@ -799,8 +800,10 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
/* ----------------------------------------- */
-/* NOTE: when this function returns true, the F-Curve is to be skipped */
-static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
+/* 'Only Selected' selected data filtering
+ * NOTE: when this function returns true, the F-Curve is to be skipped
+ */
+static size_t skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id, int filter_mode)
{
if (GS(owner_id->name) == ID_OB) {
Object *ob= (Object *)owner_id;
@@ -818,11 +821,12 @@ static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id
/* check whether to continue or skip */
if ((pchan) && (pchan->bone)) {
/* if only visible channels, skip if bone not visible unless user wants channels from hidden data too */
- if ((filter_mode & ANIMFILTER_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
+ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
bArmature *arm= (bArmature *)ob->data;
if ((arm->layer & pchan->bone->layer) == 0)
return 1;
+ // TODO: manually hidden using flags
}
/* can only add this F-Curve if it is selected */
@@ -871,8 +875,39 @@ static int skip_fcurve_selected_data (bDopeSheet *ads, FCurve *fcu, ID *owner_id
return 0;
}
+/* (Display-)Name-based F-Curve filtering
+ * NOTE: when this function returns true, the F-Curve is to be skipped
+ */
+static short skip_fcurve_with_name (bDopeSheet *ads, FCurve *fcu, ID *owner_id)
+{
+ bAnimListElem ale_dummy = {0};
+ bAnimChannelType *acf;
+
+ /* create a dummy wrapper for the F-Curve */
+ ale_dummy.type = ANIMTYPE_FCURVE;
+ ale_dummy.id = owner_id;
+ ale_dummy.data = fcu;
+
+ /* get type info for channel */
+ acf = ANIM_channel_get_typeinfo(&ale_dummy);
+ if (acf && acf->name) {
+ char name[256]; /* hopefully this will be enough! */
+
+ /* get name */
+ acf->name(&ale_dummy, name);
+
+ /* check for partial match with the match string, assuming case insensitive filtering
+ * if match, this channel shouldn't be ignored!
+ */
+ return BLI_strcasestr(name, ads->searchstr) == NULL;
+ }
+
+ /* just let this go... */
+ return 1;
+}
+
/* find the next F-Curve that is usable for inclusion */
-static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
+static FCurve *animfilter_fcurve_next (bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
{
FCurve *fcu = NULL;
@@ -880,7 +915,7 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct
* NOTE: we need to check if the F-Curves belong to the same group, as this gets called for groups too...
*/
for (fcu= first; ((fcu) && (fcu->grp==grp)); fcu= fcu->next) {
- /* special exception for Pose-Channel Based F-Curves:
+ /* special exception for Pose-Channel/Sequence-Strip/Node Based F-Curves:
* - the 'Only Selected' data filter should be applied to Pose-Channel data too, but those are
* represented as F-Curves. The way the filter for objects worked was to be the first check
* after 'normal' visibility, so this is done first here too...
@@ -892,15 +927,21 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct
if (skip_fcurve_selected_data(ads, fcu, owner_id, filter_mode))
continue;
}
-
+
/* only include if visible (Graph Editor check, not channels check) */
- if (!(filter_mode & ANIMFILTER_CURVEVISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
+ if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || (fcu->flag & FCURVE_VISIBLE)) {
/* only work with this channel and its subchannels if it is editable */
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_FCU(fcu)) {
/* only include this curve if selected in a way consistent with the filtering requirements */
if ( ANIMCHANNEL_SELOK(SEL_FCU(fcu)) && ANIMCHANNEL_SELEDITOK(SEL_FCU(fcu)) ) {
/* only include if this curve is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (fcu->flag & FCURVE_ACTIVE)) {
+ /* name based filtering... */
+ if ( ((ads) && (ads->filterflag & ADS_FILTER_BY_FCU_NAME)) && (owner_id) ) {
+ if (skip_fcurve_with_name(ads, fcu, owner_id))
+ continue;
+ }
+
/* this F-Curve can be used, so return it */
return fcu;
}
@@ -913,10 +954,10 @@ static FCurve *animdata_filter_fcurve_next (bDopeSheet *ads, FCurve *first, bAct
return NULL;
}
-static int animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, void *owner, short ownertype, int filter_mode, ID *owner_id)
+static size_t animfilter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve *first, bActionGroup *grp, int filter_mode, ID *owner_id)
{
FCurve *fcu;
- int items = 0;
+ size_t items = 0;
/* loop over every F-Curve able to be included
* - this for-loop works like this:
@@ -927,26 +968,98 @@ static int animdata_filter_fcurves (ListBase *anim_data, bDopeSheet *ads, FCurve
* 4) the fcu pointer is set to the F-Curve after the one we just added, so that we can keep going through
* the rest of the F-Curve list without an eternal loop. Back to step 2 :)
*/
- for (fcu=first; ( (fcu = animdata_filter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
+ for (fcu=first; ( (fcu = animfilter_fcurve_next(ads, fcu, grp, filter_mode, owner_id)) ); fcu=fcu->next)
+ {
+ ANIMCHANNEL_NEW_CHANNEL(fcu, ANIMTYPE_FCURVE, owner_id);
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+static size_t animfilter_act_group (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, bActionGroup *agrp, int filter_mode, ID *owner_id)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+ //int ofilter = filter_mode;
+
+ /* if we care about the selection status of the channels,
+ * but the group isn't expanded (1)...
+ * (1) this only matters if we actually care about the hierarchy though.
+ * - Hierarchy matters: this hack should be applied
+ * - Hierarchy ignored: cases like [#21276] won't work properly, unless we skip this hack
+ */
+ if ( ((filter_mode & ANIMFILTER_LIST_VISIBLE) && EXPANDED_AGRP(ac, agrp)==0) && /* care about hierarchy but group isn't expanded */
+ (filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) ) /* care about selection status */
{
- bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner, ownertype, owner_id);
+ /* if the group itself isn't selected appropriately, we shouldn't consider it's children either */
+ if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0)
+ return 0;
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ /* if we're still here, then the selection status of the curves within this group should not matter,
+ * since this creates too much overhead for animators (i.e. making a slow workflow)
+ *
+ * Tools affected by this at time of coding (2010 Feb 09):
+ * - inserting keyframes on selected channels only
+ * - pasting keyframes
+ * - creating ghost curves in Graph Editor
+ */
+ filter_mode &= ~(ANIMFILTER_SEL|ANIMFILTER_UNSEL|ANIMFILTER_LIST_VISIBLE);
+ }
+
+ /* add grouped F-Curves */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_AGRP(ac, agrp))
+ {
+ /* special filter so that we can get just the F-Curves within the active group */
+ if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
+ /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
+ * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing
+ * all its sub-curves to be shown
+ */
+ if ( !(filter_mode & ANIMFILTER_CURVE_VISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
+ {
+ /* group must be editable for its children to be editable (if we care about this) */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
+ /* get first F-Curve which can be used here */
+ FCurve *first_fcu = animfilter_fcurve_next(ads, agrp->channels.first, agrp, filter_mode, owner_id);
+
+ /* filter list, starting from this F-Curve */
+ tmp_items += animfilter_fcurves(&tmp_data, ads, first_fcu, agrp, filter_mode, owner_id);
+ }
+ }
}
}
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* add this group as a channel first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* restore original filter mode so that this next step works ok... */
+ //filter_mode = ofilter;
+
+ /* filter selection of channel specially here again, since may be open and not subject to previous test */
+ if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
+ ANIMCHANNEL_NEW_CHANNEL(agrp, ANIMTYPE_GROUP, owner_id);
+ }
+ }
+
+ /* 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;
}
-static int animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, void *owner, short ownertype, ID *owner_id)
+static size_t animfilter_action (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAction *act, int filter_mode, ID *owner_id)
{
- bAnimListElem *ale=NULL;
bActionGroup *agrp;
- FCurve *lastchan=NULL;
- int items = 0;
+ FCurve *lastchan = NULL;
+ size_t items = 0;
/* don't include anything from this action if it is linked in from another file,
* and we're getting stuff for editing...
@@ -954,106 +1067,22 @@ static int animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeS
// TODO: need a way of tagging other channels that may also be affected...
if ((filter_mode & ANIMFILTER_FOREDIT) && (act->id.lib))
return 0;
-
- /* loop over groups */
- // TODO: in future, should we expect to need nested groups?
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- FCurve *first_fcu;
- int filter_gmode;
+ /* do groups */
+ // TODO: do nested groups?
+ for (agrp = act->groups.first; agrp; agrp = agrp->next) {
/* store reference to last channel of group */
if (agrp->channels.last)
lastchan= agrp->channels.last;
-
-
- /* make a copy of filtering flags for use by the sub-channels of this group */
- filter_gmode= filter_mode;
-
- /* if we care about the selection status of the channels,
- * but the group isn't expanded...
- */
- if ( (filter_mode & (ANIMFILTER_SEL|ANIMFILTER_UNSEL)) && /* care about selection status */
- (EXPANDED_AGRP(agrp)==0) ) /* group isn't expanded */
- {
- /* if the group itself isn't selected appropriately, we shouldn't consider it's children either */
- if (ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) == 0)
- continue;
-
- /* if we're still here, then the selection status of the curves within this group should not matter,
- * since this creates too much overhead for animators (i.e. making a slow workflow)
- *
- * Tools affected by this at time of coding (2010 Feb 09):
- * - inserting keyframes on selected channels only
- * - pasting keyframes
- * - creating ghost curves in Graph Editor
- */
- filter_gmode &= ~(ANIMFILTER_SEL|ANIMFILTER_UNSEL);
- }
-
-
- /* get the first F-Curve in this group we can start to use, and if there isn't any F-Curve to start from,
- * then don't use this group at all...
- *
- * NOTE: use filter_gmode here not filter_mode, since there may be some flags we shouldn't consider under certain circumstances
- */
- first_fcu = animdata_filter_fcurve_next(ads, agrp->channels.first, agrp, filter_gmode, owner_id);
-
- /* Bug note:
- * Selecting open group to toggle visbility of the group, where the F-Curves of the group are not suitable
- * for inclusion due to their selection status (vs visibility status of bones/etc., as is usually the case),
- * will not work, since the group gets skipped. However, fixing this can easily reintroduce the bugs whereby
- * hidden groups (due to visibility status of bones/etc.) that were selected before becoming invisible, can
- * easily get deleted accidentally as they'd be included in the list filtered for that purpose.
- *
- * So, for now, best solution is to just leave this note here, and hope to find a solution at a later date.
- * -- Joshua Leung, 2010 Feb 10
- */
- if (first_fcu) {
- /* add this group as a channel first */
- if ((filter_mode & ANIMFILTER_CHANNELS) || !(filter_mode & ANIMFILTER_CURVESONLY)) {
- /* filter selection of channel specially here again, since may be open and not subject to previous test */
- if ( ANIMCHANNEL_SELOK(SEL_AGRP(agrp)) ) {
- ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE, owner_id);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
- }
- /* there are some situations, where only the channels of the action group should get considered */
- if (!(filter_mode & ANIMFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
- /* filters here are a bit convoulted...
- * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
- * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
- *
- * cases when we should include F-Curves inside group:
- * - we don't care about visibility
- * - group is expanded
- * - we just need the F-Curves present
- */
- if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || (filter_mode & ANIMFILTER_CURVESONLY) )
- {
- /* for the Graph Editor, curves may be set to not be visible in the view to lessen clutter,
- * but to do this, we need to check that the group doesn't have it's not-visible flag set preventing
- * all its sub-curves to be shown
- */
- if ( !(filter_mode & ANIMFILTER_CURVEVISIBLE) || !(agrp->flag & AGRP_NOTVISIBLE) )
- {
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
- /* NOTE: filter_gmode is used here, not standard filter_mode, since there may be some flags that shouldn't apply */
- items += animdata_filter_fcurves(anim_data, ads, first_fcu, agrp, owner, ownertype, filter_gmode, owner_id);
- }
- }
- }
- }
- }
+ /* action group's channels */
+ items += animfilter_act_group(ac, anim_data, ads, act, agrp, filter_mode, owner_id);
}
- /* loop over un-grouped F-Curves (only if we're not only considering those channels in the animive group) */
+ /* un-grouped F-Curves (only if we're not only considering those channels in the active group) */
if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
- // XXX the 'owner' info here needs review...
- items += animdata_filter_fcurves(anim_data, ads, (lastchan)?(lastchan->next):(act->curves.first), NULL, owner, ownertype, filter_mode, owner_id);
+ FCurve *firstfcu = (lastchan)? (lastchan->next) : (act->curves.first);
+ items += animfilter_fcurves(anim_data, ads, firstfcu, NULL, filter_mode, owner_id);
}
/* return the number of items added to the list */
@@ -1061,35 +1090,35 @@ static int animdata_filter_action (bAnimContext *ac, ListBase *anim_data, bDopeS
}
/* Include NLA-Data for NLA-Editor:
- * - when ANIMFILTER_CHANNELS is used, that means we should be filtering the list for display
+ * - when ANIMFILTER_LIST_CHANNELS is used, that means we should be filtering the list for display
* Although the evaluation order is from the first track to the last and then apply the Action on top,
* we present this in the UI as the Active Action followed by the last track to the first so that we
* get the evaluation order presented as per a stack.
* - for normal filtering (i.e. for editing), we only need the NLA-tracks but they can be in 'normal' evaluation
* order, i.e. first to last. Otherwise, some tools may get screwed up.
*/
-static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *UNUSED(ads), AnimData *adt, int filter_mode, void *owner, short ownertype, ID *owner_id)
+static size_t animfilter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, bDopeSheet *ads, AnimData *adt, int filter_mode, ID *owner_id)
{
- bAnimListElem *ale;
NlaTrack *nlt;
NlaTrack *first=NULL, *next=NULL;
- int items = 0;
+ size_t items = 0;
/* if showing channels, include active action */
- if (filter_mode & ANIMFILTER_CHANNELS) {
- /* there isn't really anything editable here, so skip if need editable */
- // TODO: currently, selection isn't checked since it doesn't matter
- if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
- /* just add the action track now (this MUST appear for drawing)
- * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
- * overwrite this with the real value - REVIEW THIS...
- */
- ale= make_new_animlistelem((void *)(&adt->action), ANIMTYPE_NLAACTION, owner, ownertype, owner_id);
- ale->data= (adt->action) ? adt->action : NULL;
-
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* if NLA action-line filtering is off, don't show unless there are keyframes,
+ * in order to keep things more compact for doing transforms
+ */
+ if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || (adt->action)) {
+ /* there isn't really anything editable here, so skip if need editable */
+ if ((filter_mode & ANIMFILTER_FOREDIT) == 0) {
+ /* just add the action track now (this MUST appear for drawing)
+ * - as AnimData may not have an action, we pass a dummy pointer just to get the list elem created, then
+ * overwrite this with the real value - REVIEW THIS...
+ */
+ ANIMCHANNEL_NEW_CHANNEL_FULL((void *)(&adt->action), ANIMTYPE_NLAACTION, owner_id,
+ {
+ ale->data= adt->action ? adt->action : NULL;
+ });
}
}
@@ -1104,7 +1133,7 @@ static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, b
/* loop over NLA Tracks - assume that the caller of this has already checked that these should be included */
for (nlt= first; nlt; nlt= next) {
/* 'next' NLA-Track to use depends on whether we're filtering for drawing or not */
- if (filter_mode & ANIMFILTER_CHANNELS)
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS)
next= nlt->prev;
else
next= nlt->next;
@@ -1122,12 +1151,7 @@ static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, b
if ( ANIMCHANNEL_SELOK(SEL_NLT(nlt)) ) {
/* only include if this track is active */
if (!(filter_mode & ANIMFILTER_ACTIVE) || (nlt->flag & NLATRACK_ACTIVE)) {
- ale= make_new_animlistelem(nlt, ANIMTYPE_NLATRACK, owner, ownertype, owner_id);
-
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
+ ANIMCHANNEL_NEW_CHANNEL(nlt, ANIMTYPE_NLATRACK, owner_id);
}
}
}
@@ -1137,14 +1161,44 @@ static int animdata_filter_nla (bAnimContext *UNUSED(ac), ListBase *anim_data, b
return items;
}
+/* determine what animation data from AnimData block should get displayed */
+static size_t animfilter_block_data (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *id, int filter_mode)
+{
+ IdAdtTemplate *iat = (IdAdtTemplate*)id;
+ AnimData *adt = BKE_animdata_from_id(id);
+ size_t items = 0;
+
+ /* NOTE: this macro is used instead of inlining the logic here, since this sort of filtering is still needed
+ * in a few places in he rest of the code still - notably for the few cases where special mode-based
+ * different types of data expanders are required.
+ */
+ ANIMDATA_FILTER_CASES(iat,
+ { /* AnimData */
+ /* specifically filter animdata block */
+ ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id);
+ },
+ { /* NLA */
+ items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id);
+ },
+ { /* Drivers */
+ items += animfilter_fcurves(anim_data, ads, adt->drivers.first, NULL, filter_mode, id);
+ },
+ { /* Keyframes */
+ items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
+ });
+
+ return items;
+}
+
+
+
/* Include ShapeKey Data for ShapeKey Editor */
-static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode)
+static size_t animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key *key, int filter_mode)
{
- bAnimListElem *ale;
- int items = 0;
+ size_t items = 0;
/* check if channels or only F-Curves */
- if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
KeyBlock *kb;
/* loop through the channels adding ShapeKeys as appropriate */
@@ -1160,24 +1214,21 @@ static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key
// TODO: consider 'active' too?
/* owner-id here must be key so that the F-Curve can be resolved... */
- ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key);
-
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
+ ANIMCHANNEL_NEW_CHANNEL(kb, ANIMTYPE_SHAPEKEY, key);
}
}
}
}
else {
/* just use the action associated with the shapekey */
- // FIXME: is owner-id and having no owner/dopesheet really fine?
+ // TODO: somehow manage to pass dopesheet info down here too?
if (key->adt) {
- if (filter_mode & ANIMFILTER_ANIMDATA)
- ANIMDATA_ADD_ANIMDATA(key)
- else if (key->adt->action)
- items= animdata_filter_action(ac, anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key);
+ if (filter_mode & ANIMFILTER_ANIMDATA) {
+ ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key);
+ }
+ else if (key->adt->action) {
+ items= animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key);
+ }
}
}
@@ -1185,53 +1236,102 @@ static int animdata_filter_shapekey (bAnimContext *ac, ListBase *anim_data, Key
return items;
}
+static size_t animdata_filter_gpencil_data (ListBase *anim_data, bGPdata *gpd, int filter_mode)
+{
+ bGPDlayer *gpl;
+ size_t items = 0;
+
+ /* loop over layers as the conditions are acceptable */
+ for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
+ /* only if selected */
+ if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
+ /* only if editable */
+ if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
+ /* active... */
+ if (!(filter_mode & ANIMFILTER_ACTIVE) || (gpl->flag & GP_LAYER_ACTIVE)) {
+ /* add to list */
+ ANIMCHANNEL_NEW_CHANNEL(gpl, ANIMTYPE_GPLAYER, gpd);
+ }
+ }
+ }
+ }
+
+ return items;
+}
+
/* 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)
+static size_t animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int filter_mode)
{
- bAnimListElem *ale;
bGPdata *gpd;
- bGPDlayer *gpl;
- int items = 0;
+ size_t items = 0;
- /* check if filtering types are appropriate */
- if (!(filter_mode & (ANIMFILTER_ACTGROUPED|ANIMFILTER_CURVESONLY)))
- {
- /* 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;
+ /* for now, grab grease pencil datablocks directly from main */
+ // XXX: this is not good...
+ for (gpd = G.main->gpencil.first; gpd; gpd = gpd->id.next) {
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* 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, NULL, ANIMTYPE_NONE, NULL);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
+ /* add gpencil animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_GPD(gpd))
+ {
+ tmp_items += animdata_filter_gpencil_data(&tmp_data, gpd, 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(gpd, ANIMTYPE_GPDATABLOCK, NULL);
}
- /* only add layers if they will be visible (if drawing channels) */
- if ( !(filter_mode & ANIMFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
- /* loop over layers as the conditions are acceptable */
- for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
- /* only if selected */
- if ( ANIMCHANNEL_SELOK(SEL_GPL(gpl)) ) {
- /* only if editable */
- if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
- /* add to list */
- ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK, (ID*)gpd);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
- }
- }
+ /* 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 */
+// 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)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add nodetree animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_NTREE_DATA(ntree))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ntree, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if ANIMCHANNEL_ACTIVEOK(ntree) {
+ ANIMCHANNEL_NEW_CHANNEL(ntree, ANIMTYPE_DSNTREE, owner_id);
}
}
+
+ /* 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 */
@@ -1239,16 +1339,11 @@ static int animdata_filter_gpencil (ListBase *anim_data, void *UNUSED(data), int
}
/* 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)
+static size_t animdata_filter_ds_textures (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, ID *owner_id, int filter_mode)
{
- ListBase texs = {NULL, NULL};
- LinkData *ld;
MTex **mtex = NULL;
- short expanded=0;
- int ownertype = ANIMTYPE_NONE;
-
- bAnimListElem *ale=NULL;
- int items=0, a=0;
+ size_t items=0;
+ int a=0;
/* get datatype specific data first */
if (owner_id == NULL)
@@ -1258,28 +1353,19 @@ static int animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data
case ID_MA:
{
Material *ma= (Material *)owner_id;
-
mtex= (MTex**)(&ma->mtex);
- expanded= FILTER_TEX_MATC(ma);
- ownertype= ANIMTYPE_DSMAT;
}
break;
case ID_LA:
{
Lamp *la= (Lamp *)owner_id;
-
mtex= (MTex**)(&la->mtex);
- expanded= FILTER_TEX_LAMC(la);
- ownertype= ANIMTYPE_DSLAM;
}
break;
case ID_WO:
{
World *wo= (World *)owner_id;
-
mtex= (MTex**)(&wo->mtex);
- expanded= FILTER_TEX_WORC(wo);
- ownertype= ANIMTYPE_DSWOR;
}
break;
default:
@@ -1294,235 +1380,137 @@ static int animdata_filter_dopesheet_texs (bAnimContext *ac, ListBase *anim_data
/* firstly check that we actuallly have some textures, by gathering all textures in a temp list */
for (a=0; a < MAX_MTEX; a++) {
Tex *tex= (mtex[a]) ? mtex[a]->tex : NULL;
- short ok = 0;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
/* for now, if no texture returned, skip (this shouldn't confuse the user I hope) */
- if (ELEM(NULL, tex, tex->adt))
+ if (tex == NULL)
continue;
- /* check if ok */
- ANIMDATA_FILTER_CASES(tex,
- { /* AnimData blocks - do nothing... */ },
- ok=1;,
- ok=1;,
- ok=1;)
- if (ok == 0) continue;
-
- /* make a temp list elem for this */
- ld= MEM_callocN(sizeof(LinkData), "DopeSheet-TextureCache");
- ld->data= tex;
- BLI_addtail(&texs, ld);
- }
-
- /* if there were no channels found, no need to carry on */
- if (texs.first == NULL)
- return 0;
-
- /* include textures-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(owner_id, ANIMTYPE_FILLTEXD, owner_id, ownertype, owner_id);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add textures */
- if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- /* for each texture in cache, add channels */
- for (ld= texs.first; ld; ld= ld->next) {
- Tex *tex= (Tex *)ld->data;
+ /* add texture's animation data to temp collection */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_TEX_DATA(tex))
+ {
+ /* texture animdata */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)tex, filter_mode);
+ /* nodes */
+ if ((tex->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
+ /* owner_id as id instead of texture, since it'll otherwise be impossible to track the depth */
+ // FIXME: perhaps as a result, textures should NOT be included under materials, but under their own section instead
+ // so that free-floating textures can also be animated
+ tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)tex, tex->nodetree, filter_mode);
+ }
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
/* include texture-expand widget? */
- if (filter_mode & ANIMFILTER_CHANNELS) {
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(tex) {
- ale= make_new_animlistelem(tex, ANIMTYPE_DSTEX, owner_id, ownertype, owner_id);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
+ ANIMCHANNEL_NEW_CHANNEL(tex, ANIMTYPE_DSTEX, owner_id);
}
}
- /* add texture's animation data
- * NOTE: for these, we make the owner/ownertype the material/lamp/etc. not the texture, otherwise the
- * drawing code cannot resolve the indention easily
- */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_TEX_DATA(tex) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- ANIMDATA_FILTER_CASES(tex,
- { /* AnimData blocks - do nothing... */ },
- items += animdata_filter_nla(ac, anim_data, ads, tex->adt, filter_mode, owner_id, ownertype, (ID *)tex);,
- items += animdata_filter_fcurves(anim_data, ads, tex->adt->drivers.first, NULL, owner_id, ownertype, filter_mode, (ID *)tex);,
- items += animdata_filter_action(ac, anim_data, ads, tex->adt->action, filter_mode, owner_id, ownertype, (ID *)tex);)
- }
+ /* 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;
}
}
- /* free cache */
- BLI_freelistN(&texs);
-
/* return the number of items added to the list */
return items;
}
-static int animdata_filter_dopesheet_mats (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static size_t animdata_filter_ds_materials (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- ListBase mats = {NULL, NULL};
- LinkData *ld;
-
- bAnimListElem *ale=NULL;
- Object *ob= base->object;
- int items=0, a=0;
+ size_t items=0;
+ int a=0;
/* firstly check that we actuallly have some materials, by gathering all materials in a temp list */
for (a=1; a <= ob->totcol; a++) {
Material *ma= give_current_material(ob, a);
- short ok = 0;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
- /* for now, if no material returned, skip (this shouldn't confuse the user I hope) */
+ /* if no material returned, skip - so that we don't get weird blank entries... */
if (ma == NULL) continue;
-
- /* check if ok */
- ANIMDATA_FILTER_CASES(ma,
- { /* AnimData blocks - do nothing... */ },
- ok=1;,
- ok=1;,
- ok=1;)
-
- /* need to check textures */
- if (ok == 0 && !(ads->filterflag & ADS_FILTER_NOTEX)) {
- int mtInd;
-
- for (mtInd=0; mtInd < MAX_MTEX; mtInd++) {
- MTex *mtex = ma->mtex[mtInd];
-
- if(mtex && mtex->tex) {
- ANIMDATA_FILTER_CASES(mtex->tex,
- { /* AnimData blocks - do nothing... */ },
- ok=1;,
- ok=1;,
- ok=1;)
- }
-
- if(ok)
- break;
- }
- }
-
- if (ok == 0) continue;
- /* make a temp list elem for this */
- ld= MEM_callocN(sizeof(LinkData), "DopeSheet-MaterialCache");
- ld->data= ma;
- BLI_addtail(&mats, ld);
- }
-
- /* if there were no channels found, no need to carry on */
- if (mats.first == NULL)
- return 0;
-
- /* include materials-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ /* add material's animation data to temp collection */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_MAT_OBJD(ma))
+ {
+ /* material's animation data */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ma, filter_mode);
+
+ /* textures */
+ if (!(ads->filterflag & ADS_FILTER_NOTEX))
+ tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)ma, filter_mode);
+
+ /* nodes */
+ if ((ma->nodetree) && !(ads->filterflag & ADS_FILTER_NONTREE))
+ tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)ma, ma->nodetree, filter_mode);
}
- }
-
- /* add materials? */
- if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- /* for each material in cache, add channels */
- for (ld= mats.first; ld; ld= ld->next) {
- Material *ma= (Material *)ld->data;
-
- /* include material-expand widget? */
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include material-expand widget first */
// hmm... do we need to store the index of this material in the array anywhere?
- if (filter_mode & ANIMFILTER_CHANNELS) {
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(ma) {
- ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT, (ID *)ma);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
+ ANIMCHANNEL_NEW_CHANNEL(ma, ANIMTYPE_DSMAT, ma);
}
}
- /* add material's animation data */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- /* material's animation data */
- ANIMDATA_FILTER_CASES(ma,
- { /* AnimData blocks - do nothing... */ },
- items += animdata_filter_nla(ac, anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);,
- items += animdata_filter_fcurves(anim_data, ads, ma->adt->drivers.first, NULL, ma, ANIMTYPE_DSMAT, filter_mode, (ID *)ma);,
- items += animdata_filter_action(ac, anim_data, ads, ma->adt->action, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);)
-
- /* textures */
- if (!(ads->filterflag & ADS_FILTER_NOTEX))
- items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)ma, filter_mode);
- }
+ /* 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;
}
}
- /* free cache */
- BLI_freelistN(&mats);
-
/* return the number of items added to the list */
return items;
}
-static int animdata_filter_dopesheet_particles (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static size_t animdata_filter_ds_particles (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- bAnimListElem *ale=NULL;
- Object *ob= base->object;
- ParticleSystem *psys = ob->particlesystem.first;
- int items= 0, first = 1;
-
- for(; psys; psys=psys->next) {
- short ok = 0;
+ ParticleSystem *psys;
+ size_t items= 0;
- if(ELEM(NULL, psys->part, psys->part->adt))
+ for (psys = ob->particlesystem.first; psys; psys=psys->next) {
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+
+ /* if no material returned, skip - so that we don't get weird blank entries... */
+ if (ELEM(NULL, psys->part, psys->part->adt))
continue;
-
- ANIMDATA_FILTER_CASES(psys->part,
- { /* AnimData blocks - do nothing... */ },
- ok=1;,
- ok=1;,
- ok=1;)
- if (ok == 0) continue;
-
- /* include particles-expand widget? */
- if (first && (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(ob, ANIMTYPE_FILLPARTD, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- first = 0;
+
+ /* add particle-system's animation data to temp collection */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_PART_OBJD(psys->part))
+ {
+ /* material's animation data */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)psys->part, filter_mode);
}
+ END_ANIMFILTER_SUBCHANNELS;
- /* add particle settings? */
- if (FILTER_PART_OBJC(ob) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- if ((filter_mode & ANIMFILTER_CHANNELS)) {
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include particle-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by active status */
if ANIMCHANNEL_ACTIVEOK(psys->part) {
- ale = make_new_animlistelem(psys->part, ANIMTYPE_DSPART, base, ANIMTYPE_OBJECT, (ID *)psys->part);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
+ ANIMCHANNEL_NEW_CHANNEL(psys->part, ANIMTYPE_DSPART, psys->part);
}
}
- if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- ANIMDATA_FILTER_CASES(psys->part,
- { /* AnimData blocks - do nothing... */ },
- items += animdata_filter_nla(ac, anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);,
- items += animdata_filter_fcurves(anim_data, ads, psys->part->adt->drivers.first, NULL, psys->part, ANIMTYPE_DSPART, filter_mode, (ID *)psys->part);,
- items += animdata_filter_action(ac, anim_data, ads, psys->part->adt->action, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);)
- }
+ /* 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;
}
}
@@ -1530,14 +1518,14 @@ static int animdata_filter_dopesheet_particles (bAnimContext *ac, ListBase *anim
return items;
}
-static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+static size_t animdata_filter_ds_obdata (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
{
- bAnimListElem *ale=NULL;
- Object *ob= base->object;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items= 0;
+
IdAdtTemplate *iat= ob->data;
- AnimData *adt= iat->adt;
short type=0, expanded=0;
- int items= 0;
/* get settings based on data type */
switch (ob->type) {
@@ -1545,6 +1533,9 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
Camera *ca= (Camera *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOCAM)
+ return 0;
+
type= ANIMTYPE_DSCAM;
expanded= FILTER_CAM_OBJD(ca);
}
@@ -1553,6 +1544,9 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
Lamp *la= (Lamp *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOLAM)
+ return 0;
+
type= ANIMTYPE_DSLAM;
expanded= FILTER_LAM_OBJD(la);
}
@@ -1563,6 +1557,9 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
Curve *cu= (Curve *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOCUR)
+ return 0;
+
type= ANIMTYPE_DSCUR;
expanded= FILTER_CUR_OBJD(cu);
}
@@ -1571,6 +1568,9 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
MetaBall *mb= (MetaBall *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOMBA)
+ return 0;
+
type= ANIMTYPE_DSMBALL;
expanded= FILTER_MBALL_OBJD(mb);
}
@@ -1579,6 +1579,9 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
bArmature *arm= (bArmature *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOARM)
+ return 0;
+
type= ANIMTYPE_DSARM;
expanded= FILTER_ARM_OBJD(arm);
}
@@ -1587,6 +1590,9 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
Mesh *me= (Mesh *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOMESH)
+ return 0;
+
type= ANIMTYPE_DSMESH;
expanded= FILTER_MESH_OBJD(me);
}
@@ -1595,467 +1601,358 @@ static int animdata_filter_dopesheet_obdata (bAnimContext *ac, ListBase *anim_da
{
Lattice *lt = (Lattice *)ob->data;
+ if (ads->filterflag & ADS_FILTER_NOLAT)
+ return 0;
+
type= ANIMTYPE_DSLAT;
expanded= FILTER_LATTICE_OBJD(lt);
}
break;
}
- /* special exception for drivers instead of action */
- if (ads->filterflag & ADS_FILTER_ONLYDRIVERS)
- expanded= EXPANDED_DRVD(adt);
-
- /* include data-expand widget? */
- if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
- /* check if filtering by active status */
- if ANIMCHANNEL_ACTIVEOK(iat) {
- ale= make_new_animlistelem(iat, type, base, ANIMTYPE_OBJECT, (ID *)iat);
- if (ale) BLI_addtail(anim_data, ale);
- }
- }
-
- /* add object-data animation channels? */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- /* filtering for channels - nla, drivers, keyframes */
- ANIMDATA_FILTER_CASES(iat,
- { /* AnimData blocks - do nothing... */ },
- items+= animdata_filter_nla(ac, anim_data, ads, iat->adt, filter_mode, iat, type, (ID *)iat);,
- items+= animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, iat, type, filter_mode, (ID *)iat);,
- items+= animdata_filter_action(ac, anim_data, ads, iat->adt->action, filter_mode, iat, type, (ID *)iat);)
-
+ /* add object data animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)iat, filter_mode);
+
/* sub-data filtering... */
switch (ob->type) {
case OB_LAMP: /* lamp - textures */
{
/* textures */
if (!(ads->filterflag & ADS_FILTER_NOTEX))
- items += animdata_filter_dopesheet_texs(ac, anim_data, ads, ob->data, filter_mode);
+ tmp_items += animdata_filter_ds_textures(ac, &tmp_data, ads, ob->data, filter_mode);
}
break;
}
}
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if ANIMCHANNEL_ACTIVEOK(iat) {
+ ANIMCHANNEL_NEW_CHANNEL(iat, type, iat);
+ }
+ }
+
+ /* 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;
}
-static int animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+/* shapekey-level animation */
+static size_t animdata_filter_ds_keyanim (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, Key *key, int filter_mode)
{
- bAnimListElem *ale=NULL;
- AnimData *adt = NULL;
- Object *ob= base->object;
- Key *key= ob_get_key(ob);
- short obdata_ok = 0;
- int items = 0;
-
- /* add this object as a channel first */
- if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
- /* check if filtering by selection */
- if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
- /* check if filtering by active status */
- if ANIMCHANNEL_ACTIVEOK(ob) {
- ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
- }
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add shapekey-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_SKE_OBJD(key))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)key, filter_mode);
}
+ END_ANIMFILTER_SUBCHANNELS;
- /* if collapsed, don't go any further (unless adding keyframes only) */
- if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) &&
- !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
- return items;
-
- /* Action, Drivers, or NLA */
- if (ob->adt && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
- adt= ob->adt;
- ANIMDATA_FILTER_CASES(ob,
- { /* AnimData blocks - do nothing... */ },
- { /* nla */
- /* add NLA tracks */
- items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
- },
- { /* drivers */
- /* include drivers-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add F-Curve channels (drivers are F-Curves) */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
- items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
- }
- },
- { /* action (keyframes) */
- /* include action-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add F-Curve channels? */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
- items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)ob);
- }
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include key-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ if ANIMCHANNEL_ACTIVEOK(key) {
+ ANIMCHANNEL_NEW_CHANNEL(key, ANIMTYPE_DSSKEY, ob);
}
- );
+ }
+
+ /* 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;
+}
+
+/* object-level animation */
+static size_t animdata_filter_ds_obanim (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Object *ob, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ AnimData *adt = ob->adt;
+ short type=0, expanded=1;
+ void *cdata = NULL;
+
+ /* determine the type of expander channels to use */
+ // this is the best way to do this for now...
+ ANIMDATA_FILTER_CASES(ob,
+ {/* AnimData - no channel, but consider data */},
+ {/* NLA - no channel, but consider data */},
+ {/* Drivers */
+ type = ANIMTYPE_FILLDRIVERS;
+ cdata = adt;
+ expanded = EXPANDED_DRVD(adt);
+ },
+ {/* Keyframes */
+ type = ANIMTYPE_FILLACTD;
+ cdata = adt->action;
+ expanded = EXPANDED_ACTC(adt->action);
+ });
+
+ /* add object-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)ob, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
- /* ShapeKeys? */
- if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
- adt= key->adt;
- ANIMDATA_FILTER_CASES(key,
- { /* AnimData blocks - do nothing... */ },
- { /* nla */
- /* include shapekey-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- /* check if filtering by active status */
- if ANIMCHANNEL_ACTIVEOK(key) {
- ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
- }
-
- /* add NLA tracks - only if expanded or so */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY))
- items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ob, ANIMTYPE_OBJECT, (ID *)key);
- },
- { /* drivers */
- /* include shapekey-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add channels */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, key, ANIMTYPE_DSSKEY, filter_mode, (ID *)key);
- }
- },
- { /* action (keyframes) */
- /* include shapekey-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- /* check if filtering by active status */
- if ANIMCHANNEL_ACTIVEOK(key) {
- ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT, (ID *)ob);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
- }
-
- /* add channels */
- if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, key, ANIMTYPE_DSSKEY, (ID *)key);
- }
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ if (type != ANIMTYPE_NONE) {
+ /* NOTE: active-status (and the associated checks) don't apply here... */
+ ANIMCHANNEL_NEW_CHANNEL(cdata, type, ob);
}
- );
+ }
+
+ /* 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;
+}
- /* Materials? */
- if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
- items += animdata_filter_dopesheet_mats(ac, anim_data, ads, base, filter_mode);
+/* get animation channels from object2 */
+static size_t animdata_filter_dopesheet_ob (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ Object *ob= base->object;
+ size_t tmp_items = 0;
+ size_t items = 0;
- /* Object Data */
- switch (ob->type) {
- case OB_CAMERA: /* ------- Camera ------------ */
- {
- Camera *ca= (Camera *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOCAM) == 0) {
- ANIMDATA_FILTER_CASES(ca,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
- }
- }
- break;
- case OB_LAMP: /* ---------- Lamp ----------- */
- {
- Lamp *la= (Lamp *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOLAM) == 0) {
- ANIMDATA_FILTER_CASES(la,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
- }
+ /* filter data contained under object first */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob))
+ {
+ Key *key= ob_get_key(ob);
+
+ /* object-level animation */
+ if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
+ tmp_items += animdata_filter_ds_obanim(ac, &tmp_data, ads, ob, filter_mode);
}
- break;
- case OB_CURVE: /* ------- Curve ---------- */
- case OB_SURF: /* ------- Nurbs Surface ---------- */
- case OB_FONT: /* ------- Text Curve ---------- */
- {
- Curve *cu= (Curve *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOCUR) == 0) {
- ANIMDATA_FILTER_CASES(cu,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
- }
+
+ /* shape-key */
+ if ((key && key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
+ tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode);
}
- break;
- case OB_MBALL: /* ------- MetaBall ---------- */
- {
- MetaBall *mb= (MetaBall *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOMBA) == 0) {
- ANIMDATA_FILTER_CASES(mb,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
- }
+
+ /* materials */
+ if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT)) {
+ tmp_items += animdata_filter_ds_materials(ac, &tmp_data, ads, ob, filter_mode);
}
- break;
- case OB_ARMATURE: /* ------- Armature ---------- */
- {
- bArmature *arm= (bArmature *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOARM) == 0) {
- ANIMDATA_FILTER_CASES(arm,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
- }
+
+ /* object data */
+ if (ob->data) {
+ tmp_items += animdata_filter_ds_obdata(ac, &tmp_data, ads, ob, filter_mode);
}
- break;
- case OB_MESH: /* ------- Mesh ---------- */
- {
- Mesh *me= (Mesh *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOMESH) == 0) {
- ANIMDATA_FILTER_CASES(me,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
- }
+
+ /* particles */
+ if ((ob->particlesystem.first) && !(ads->filterflag & ADS_FILTER_NOPART)) {
+ tmp_items += animdata_filter_ds_particles(ac, &tmp_data, ads, ob, filter_mode);
}
- break;
- case OB_LATTICE: /* ------- Lattice ---------- */
- {
- Lattice *lt= (Lattice *)ob->data;
-
- if ((ads->filterflag & ADS_FILTER_NOLAT) == 0) {
- ANIMDATA_FILTER_CASES(lt,
- { /* AnimData blocks - do nothing... */ },
- obdata_ok= 1;,
- obdata_ok= 1;,
- obdata_ok= 1;)
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+
+ /* if we collected some channels, add these to the new list... */
+ if (tmp_items) {
+ /* firstly add object expander if required */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by selection */
+ // XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
+ if ANIMCHANNEL_SELOK((base->flag & SELECT)) {
+ /* check if filtering by active status */
+ if (ANIMCHANNEL_ACTIVEOK(ob)) {
+ ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob);
+ }
}
}
- break;
+
+ /* 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;
}
- if (obdata_ok)
- items += animdata_filter_dopesheet_obdata(ac, anim_data, ads, base, filter_mode);
-
- /* particles */
- if (ob->particlesystem.first && !(ads->filterflag & ADS_FILTER_NOPART))
- items += animdata_filter_dopesheet_particles(ac, anim_data, ads, base, filter_mode);
- /* return the number of items added to the list */
+ /* return the number of items added */
return items;
-}
+}
-static int animdata_filter_dopesheet_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+static size_t animdata_filter_ds_world (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
{
- World *wo= sce->world;
- bNodeTree *ntree= sce->nodetree;
- AnimData *adt= NULL;
- bAnimListElem *ale;
- int items = 0;
-
- /* add scene as a channel first (even if we aren't showing scenes we still need to show the scene's sub-data */
- if ((filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) == 0) {
- /* check if filtering by selection */
- if (ANIMCHANNEL_SELOK( (sce->flag & SCE_DS_SELECTED) )) {
- ale= make_new_animlistelem(sce, ANIMTYPE_SCENE, NULL, ANIMTYPE_NONE, NULL);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add world animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_WOR_SCED(wo))
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)wo, filter_mode);
+
+ /* textures for world */
+ if (!(ads->filterflag & ADS_FILTER_NOTEX))
+ items += animdata_filter_ds_textures(ac, &tmp_data, ads, (ID *)wo, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ if ANIMCHANNEL_ACTIVEOK(wo) {
+ ANIMCHANNEL_NEW_CHANNEL(wo, ANIMTYPE_DSWOR, sce);
}
}
+
+ /* 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;
}
- /* if collapsed, don't go any further (unless adding keyframes only) */
- if ( (EXPANDED_SCEC(sce) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
- return items;
+ /* return the number of items added to the list */
+ return items;
+}
+
+static size_t animdata_filter_ds_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ AnimData *adt = sce->adt;
+ short type=0, expanded=1;
+ void *cdata = NULL;
+
+ /* determine the type of expander channels to use */
+ // this is the best way to do this for now...
+ ANIMDATA_FILTER_CASES(sce,
+ {/* AnimData - no channel, but consider data */},
+ {/* NLA - no channel, but consider data */},
+ {/* Drivers */
+ type = ANIMTYPE_FILLDRIVERS;
+ cdata = adt;
+ expanded = EXPANDED_DRVD(adt);
+ },
+ {/* Keyframes */
+ type = ANIMTYPE_FILLACTD;
+ cdata = adt->action;
+ expanded = EXPANDED_ACTC(adt->action);
+ });
- /* Action, Drivers, or NLA for Scene */
- if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
- adt= sce->adt;
- ANIMDATA_FILTER_CASES(sce,
- { /* AnimData blocks - do nothing... */ },
- { /* nla */
- /* add NLA tracks */
- items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
- },
- { /* drivers */
- /* include drivers-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLDRIVERS, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add F-Curve channels (drivers are F-Curves) */
- if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, sce, ANIMTYPE_SCENE, filter_mode, (ID *)sce);
- }
- },
- { /* action */
- /* include action-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(adt->action, ANIMTYPE_FILLACTD, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add F-Curve channels? */
- if (EXPANDED_ACTC(adt->action) || !(filter_mode & ANIMFILTER_CHANNELS)) {
- items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, sce, ANIMTYPE_SCENE, (ID *)sce);
- }
- }
- )
+ /* add scene-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)sce, filter_mode);
}
+ END_ANIMFILTER_SUBCHANNELS;
- /* world */
- if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
- /* Action, Drivers, or NLA for World */
- adt= wo->adt;
- ANIMDATA_FILTER_CASES(wo,
- { /* AnimData blocks - do nothing... */ },
- { /* nla */
- /* add NLA tracks */
- items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
- },
- { /* drivers */
- /* include world-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)wo);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add F-Curve channels (drivers are F-Curves) */
- if (FILTER_WOR_SCED(wo)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // XXX owner info is messed up now...
- items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, wo, ANIMTYPE_DSWOR, filter_mode, (ID *)wo);
- }
- },
- { /* action */
- /* include world-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(wo, ANIMTYPE_DSWOR, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add channels */
- if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, wo, ANIMTYPE_DSWOR, (ID *)wo);
- }
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include anim-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ if (type != ANIMTYPE_NONE) {
+ /* NOTE: active-status (and the associated checks) don't apply here... */
+ ANIMCHANNEL_NEW_CHANNEL(cdata, type, sce);
}
- )
+ }
- /* if expanded, check world textures too */
- if (FILTER_WOR_SCED(wo) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- /* textures for world */
- if (!(ads->filterflag & ADS_FILTER_NOTEX))
- items += animdata_filter_dopesheet_texs(ac, anim_data, ads, (ID *)wo, filter_mode);
+ /* 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;
+}
+
+static size_t animdata_filter_dopesheet_scene (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* filter data contained under object first */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
+ {
+ bNodeTree *ntree= sce->nodetree;
+ World *wo= sce->world;
+
+ /* Action, Drivers, or NLA for Scene */
+ if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
+ tmp_items += animdata_filter_ds_scene(ac, &tmp_data, ads, sce, filter_mode);
+ }
+
+ /* world */
+ if ((wo && wo->adt) && !(ads->filterflag & ADS_FILTER_NOWOR)) {
+ tmp_items += animdata_filter_ds_world(ac, &tmp_data, ads, sce, wo, filter_mode);
+ }
+
+ /* nodetree */
+ if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
+ tmp_items += animdata_filter_ds_nodetree(ac, &tmp_data, ads, (ID *)sce, ntree, filter_mode);
}
+
+ // TODO: one day, when sequencer becomes its own datatype, perhaps it should be included here
}
- /* nodetree */
- if ((ntree && ntree->adt) && !(ads->filterflag & ADS_FILTER_NONTREE)) {
- /* Action, Drivers, or NLA for Nodetree */
- adt= ntree->adt;
- ANIMDATA_FILTER_CASES(ntree,
- { /* AnimData blocks - do nothing... */ },
- { /* nla */
- /* add NLA tracks */
- items += animdata_filter_nla(ac, anim_data, ads, adt, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
- },
- { /* drivers */
- /* include nodetree-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)ntree);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add F-Curve channels (drivers are F-Curves) */
- if (FILTER_NTREE_SCED(ntree)/*EXPANDED_DRVD(adt)*/ || !(filter_mode & ANIMFILTER_CHANNELS)) {
- // XXX owner info is messed up now...
- items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ntree, ANIMTYPE_DSNTREE, filter_mode, (ID *)ntree);
- }
- },
- { /* action */
- /* include nodetree-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_CURVESONLY)) {
- ale= make_new_animlistelem(ntree, ANIMTYPE_DSNTREE, sce, ANIMTYPE_SCENE, (ID *)sce);
- if (ale) {
- BLI_addtail(anim_data, ale);
- items++;
- }
- }
-
- /* add channels */
- if (FILTER_NTREE_SCED(ntree) || (filter_mode & ANIMFILTER_CURVESONLY)) {
- items += animdata_filter_action(ac, anim_data, ads, adt->action, filter_mode, ntree, ANIMTYPE_DSNTREE, (ID *)ntree);
- }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* if we collected some channels, add these to the new list... */
+ if (tmp_items) {
+ /* firstly add object expander if required */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by selection */
+ if ANIMCHANNEL_SELOK((sce->flag & SCE_DS_SELECTED)) {
+ /* NOTE: active-status doesn't matter for this! */
+ ANIMCHANNEL_NEW_CHANNEL(sce, ANIMTYPE_SCENE, sce);
}
- )
+ }
+
+ /* 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;
}
-
- // TODO: scene compositing nodes (these aren't standard node-trees)
-
- /* return the number of items added to the list */
+ /* return the number of items added */
return items;
}
// TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
-static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
+static size_t animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
{
Scene *sce= (Scene *)ads->source;
Base *base;
- bAnimListElem *ale;
- int items = 0;
+ size_t items = 0;
/* check that we do indeed have a scene */
if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
@@ -2073,73 +1970,14 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo
filter_mode |= ANIMFILTER_SELEDIT;
}
- /* scene-linked animation */
- // TODO: sequencer, composite nodes - are we to include those here too?
- {
- short sceOk= 0, worOk= 0, nodeOk=0;
-
- /* check filtering-flags if ok */
- ANIMDATA_FILTER_CASES(sce,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(sce);
- sceOk=0;
- },
- sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
- sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);,
- sceOk= !(ads->filterflag & ADS_FILTER_NOSCE);)
- if (sce->world) {
- ANIMDATA_FILTER_CASES(sce->world,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(sce->world);
- worOk=0;
- },
- worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
- worOk= !(ads->filterflag & ADS_FILTER_NOWOR);,
- worOk= !(ads->filterflag & ADS_FILTER_NOWOR);)
- }
- if (sce->nodetree) {
- ANIMDATA_FILTER_CASES(sce->nodetree,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(sce->nodetree);
- nodeOk=0;
- },
- nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);,
- nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);,
- nodeOk= !(ads->filterflag & ADS_FILTER_NONTREE);)
- }
-
- /* if only F-Curves with visible flags set can be shown, check that
- * datablocks haven't been set to invisible
- */
- if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
- if ((sce->adt) && (sce->adt->flag & ADT_CURVES_NOT_VISIBLE))
- sceOk= worOk= nodeOk= 0;
- }
-
- /* check if not all bad (i.e. so there is something to show) */
- if ( !(!sceOk && !worOk && !nodeOk) ) {
- /* add scene data to the list of filtered channels */
- items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode);
- }
- }
-
+ /* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
+ items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode);
- /* loop over all bases in the scene */
+ /* loop over all bases (i.e.objects) in the scene */
for (base= sce->base.first; base; base= base->next) {
/* check if there's an object (all the relevant checks are done in the ob-function) */
if (base->object) {
Object *ob= base->object;
- Key *key= ob_get_key(ob);
- short actOk=1, keyOk=1, dataOk=1, matOk=1, partOk=1;
/* firstly, check if object can be included, by the following factors:
* - if only visible, must check for layer and also viewport visibility
@@ -2147,10 +1985,10 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo
* as user option controls whether sets of channels get included while
* tool-flag takes into account collapsed/open channels too
* - if only selected, must check if object is selected
- * - there must be animation data to edit
+ * - there must be animation data to edit (this is done recursively as we
+ * try to add the channels)
*/
- // TODO: if cache is implemented, just check name here, and then
- if ((filter_mode & ANIMFILTER_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
+ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
if ((sce->lay & (ob->lay|base->lay))==0) continue;
@@ -2161,280 +1999,26 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo
/* if only F-Curves with visible flags set can be shown, check that
* datablock hasn't been set to invisible
*/
- if (filter_mode & ANIMFILTER_CURVEVISIBLE) {
+ if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
continue;
}
- /* additionally, dopesheet filtering also affects what objects to consider */
- {
- /* check selection and object type filters */
- if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) {
- /* only selected should be shown */
- continue;
- }
-
- /* check if object belongs to the filtering group if option to filter
- * objects by the grouped status is on
- * - used to ease the process of doing multiple-character choreographies
- */
- if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (object_in_group(ob, ads->filter_grp) == 0)
- continue;
- }
-
- /* check filters for datatypes */
- /* object */
- actOk= 0;
- if (!(ads->filterflag & ADS_FILTER_NOOBJ)) {
- ANIMDATA_FILTER_CASES(ob,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(ob);
- actOk=0;
- },
- actOk= 1;,
- actOk= 1;,
- actOk= 1;)
- }
-
- keyOk= 0;
- if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
- /* shapekeys */
- ANIMDATA_FILTER_CASES(key,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(key);
- keyOk=0;
- },
- keyOk= 1;,
- keyOk= 1;,
- keyOk= 1;)
- }
-
- /* materials - only for geometric types */
- matOk= 0; /* by default, not ok... */
- if ( !(ads->filterflag & ADS_FILTER_NOMAT) && (ob->totcol) &&
- ELEM5(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL) )
- {
- int a;
-
- /* firstly check that we actuallly have some materials */
- for (a=1; a <= ob->totcol; a++) {
- Material *ma= give_current_material(ob, a);
-
- if (ma) {
- /* if material has relevant animation data, break */
- ANIMDATA_FILTER_CASES(ma,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(ma);
- matOk=0;
- },
- matOk= 1;,
- matOk= 1;,
- matOk= 1;)
-
- if (matOk)
- break;
-
- /* textures? */
- // TODO: make this a macro that is used in the other checks too
- // NOTE: this has little use on its own, since the actual filtering still ignores if no anim on the data
- if (!(ads->filterflag & ADS_FILTER_NOTEX)) {
- int mtInd;
-
- for (mtInd= 0; mtInd < MAX_MTEX; mtInd++) {
- MTex *mtex= ma->mtex[mtInd];
-
- if (mtex && mtex->tex) {
- /* if texture has relevant animation data, break */
- ANIMDATA_FILTER_CASES(mtex->tex,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(mtex->tex);
- matOk=0;
- },
- matOk= 1;,
- matOk= 1;,
- matOk= 1;)
-
- if (matOk)
- break;
- }
- }
- }
-
- }
- }
- }
-
- /* data */
- switch (ob->type) {
- case OB_CAMERA: /* ------- Camera ------------ */
- {
- Camera *ca= (Camera *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(ca,
- if ((ads->filterflag & ADS_FILTER_NOCAM)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(ca);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOCAM);)
- }
- break;
- case OB_LAMP: /* ---------- Lamp ----------- */
- {
- Lamp *la= (Lamp *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(la,
- if ((ads->filterflag & ADS_FILTER_NOLAM)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(la);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOLAM);)
- }
- break;
- case OB_CURVE: /* ------- Curve ---------- */
- case OB_SURF: /* ------- Nurbs Surface ---------- */
- case OB_FONT: /* ------- Text Curve ---------- */
- {
- Curve *cu= (Curve *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(cu,
- if ((ads->filterflag & ADS_FILTER_NOCUR)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(cu);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOCUR);)
- }
- break;
- case OB_MBALL: /* ------- MetaBall ---------- */
- {
- MetaBall *mb= (MetaBall *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(mb,
- if ((ads->filterflag & ADS_FILTER_NOMBA)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(mb);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOMBA);)
- }
- break;
- case OB_ARMATURE: /* ------- Armature ---------- */
- {
- bArmature *arm= (bArmature *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(arm,
- if ((ads->filterflag & ADS_FILTER_NOARM)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(arm);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOARM);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOARM);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOARM);)
- }
- break;
- case OB_MESH: /* ------- Mesh ---------- */
- {
- Mesh *me= (Mesh *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(me,
- if ((ads->filterflag & ADS_FILTER_NOMESH)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(me);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOMESH);)
- }
- break;
- case OB_LATTICE: /* ------- Lattice ---------- */
- {
- Lattice *lt= (Lattice *)ob->data;
- dataOk= 0;
- ANIMDATA_FILTER_CASES(lt,
- if ((ads->filterflag & ADS_FILTER_NOLAT)==0) {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(lt);
- dataOk=0;
- },
- dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);,
- dataOk= !(ads->filterflag & ADS_FILTER_NOLAT);)
- }
- break;
- default: /* --- other --- */
- dataOk= 0;
- break;
- }
-
- /* particles */
- partOk = 0;
- if (!(ads->filterflag & ADS_FILTER_NOPART) && ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
- for(; psys; psys=psys->next) {
- if (psys->part) {
- /* if particlesettings has relevant animation data, break */
- ANIMDATA_FILTER_CASES(psys->part,
- {
- /* for the special AnimData blocks only case, we only need to add
- * the block if it is valid... then other cases just get skipped (hence ok=0)
- */
- ANIMDATA_ADD_ANIMDATA(psys->part);
- partOk=0;
- },
- partOk= 1;,
- partOk= 1;,
- partOk= 1;)
- }
-
- if (partOk)
- break;
- }
- }
-
- /* check if all bad (i.e. nothing to show) */
- if (!actOk && !keyOk && !dataOk && !matOk && !partOk)
- continue;
+ /* check selection and object type filters */
+ if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) {
+ /* only selected should be shown */
+ continue;
}
+ /* check if object belongs to the filtering group if option to filter
+ * objects by the grouped status is on
+ * - used to ease the process of doing multiple-character choreographies
+ */
+ if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
+ if (object_in_group(ob, ads->filter_grp) == 0)
+ continue;
+ }
+
/* since we're still here, this object should be usable */
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
}
@@ -2447,7 +2031,7 @@ static int animdata_filter_dopesheet (bAnimContext *ac, ListBase *anim_data, bDo
/* Summary track for DopeSheet/Action Editor
* - return code is whether the summary lets the other channels get drawn
*/
-static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim_data, int filter_mode, int *items)
+static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim_data, int filter_mode, size_t *items)
{
bDopeSheet *ads = NULL;
@@ -2456,8 +2040,8 @@ static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim
* since all the other Animation Editors won't have this concept
* being applicable.
*/
- if ((ac && ac->sa) && (ac->sa->spacetype == SPACE_ACTION)) {
- SpaceAction *saction= (SpaceAction *)ac->sa->spacedata.first;
+ if ((ac && ac->sl) && (ac->spacetype == SPACE_ACTION)) {
+ SpaceAction *saction= (SpaceAction *)ac->sl;
ads= &saction->ads;
}
else {
@@ -2469,9 +2053,8 @@ static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim
* - only for drawing and/or selecting keyframes in channels, but not for real editing
* - only useful for DopeSheet/Action/etc. editors where it is actually useful
*/
- // TODO: we should really check if some other prohibited filters are also active, but that can be for later
- if ((filter_mode & ANIMFILTER_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
- bAnimListElem *ale= make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL, ANIMTYPE_NONE, NULL);
+ if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && (ads->filterflag & ADS_FILTER_SUMMARY)) {
+ bAnimListElem *ale= make_new_animlistelem(ac, ANIMTYPE_SUMMARY, NULL);
if (ale) {
BLI_addtail(anim_data, ale);
(*items)++;
@@ -2488,13 +2071,39 @@ static short animdata_filter_dopesheet_summary (bAnimContext *ac, ListBase *anim
return 1;
}
+/* ......................... */
+
+/* filter data associated with a channel - usually for handling summary-channels in DopeSheet */
+static size_t animdata_filter_animchan (bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, bAnimListElem *channel, int filter_mode)
+{
+ size_t items = 0;
+
+ /* data to filter depends on channel type */
+ // XXX: only common channel-types have been handled for now
+ switch (channel->type) {
+ case ANIMTYPE_SUMMARY:
+ items += animdata_filter_dopesheet(ac, anim_data, ads, filter_mode);
+ break;
+
+ case ANIMTYPE_SCENE:
+ items += animdata_filter_dopesheet_scene(ac, anim_data, ads, channel->data, filter_mode);
+ break;
+
+ case ANIMTYPE_OBJECT:
+ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
+ break;
+ }
+
+ return items;
+}
+
/* ----------- Cleanup API --------------- */
/* Remove entries with invalid types in animation channel list */
-static int animdata_filter_remove_invalid (ListBase *anim_data)
+static size_t animdata_filter_remove_invalid (ListBase *anim_data)
{
bAnimListElem *ale, *next;
- int items = 0;
+ size_t items = 0;
/* only keep entries with valid types */
for (ale= anim_data->first; ale; ale= next) {
@@ -2510,11 +2119,11 @@ static int animdata_filter_remove_invalid (ListBase *anim_data)
}
/* Remove duplicate entries in animation channel list */
-static int animdata_filter_remove_duplis (ListBase *anim_data)
+static size_t animdata_filter_remove_duplis (ListBase *anim_data)
{
bAnimListElem *ale, *next;
GHash *gh;
- int items = 0;
+ size_t items = 0;
/* build new hashtable to efficiently store and retrieve which entries have been
* encountered already while searching
@@ -2556,9 +2165,9 @@ static int animdata_filter_remove_duplis (ListBase *anim_data)
* will be placed for use.
* filter_mode: how should the data be filtered - bitmapping accessed flags
*/
-int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype)
+size_t ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode, void *data, short datatype)
{
- int items = 0;
+ size_t items = 0;
/* only filter data if there's somewhere to put it */
if (data && anim_data) {
@@ -2568,12 +2177,12 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
switch (datatype) {
case ANIMCONT_ACTION: /* 'Action Editor' */
{
- SpaceAction *saction = (SpaceAction *)ac->sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)ac->sl;
bDopeSheet *ads = (saction)? &saction->ads : NULL;
/* the check for the DopeSheet summary is included here since the summary works here too */
if (animdata_filter_dopesheet_summary(ac, anim_data, filter_mode, &items))
- items += animdata_filter_action(ac, anim_data, ads, data, filter_mode, NULL, ANIMTYPE_NONE, (ID *)obact);
+ items += animfilter_action(ac, anim_data, ads, data, filter_mode, (ID *)obact);
}
break;
@@ -2607,6 +2216,15 @@ int ANIM_animdata_filter (bAnimContext *ac, ListBase *anim_data, int filter_mode
items = animdata_filter_dopesheet(ac, anim_data, data, filter_mode);
}
break;
+
+ case ANIMCONT_CHANNEL: /* animation channel */
+ {
+ bDopeSheet *ads = ac->ads;
+
+ /* based on the channel type, filter relevant data for this */
+ items = animdata_filter_animchan(ac, anim_data, ads, data, filter_mode);
+ }
+ break;
}
/* remove any 'weedy' entries */
diff --git a/source/blender/editors/animation/anim_intern.h b/source/blender/editors/animation/anim_intern.h
index 274d33e4833..7818e8118a3 100644
--- a/source/blender/editors/animation/anim_intern.h
+++ b/source/blender/editors/animation/anim_intern.h
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -24,6 +24,11 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
+/** \file blender/editors/animation/anim_intern.h
+ * \ingroup edanimation
+ */
+
#ifndef ANIM_INTERN_H
#define ANIM_INTERN_H
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index 3e2212c15bb..fc05f46929b 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_ipo_utils.c
+ * \ingroup edanimation
+ */
+
+
/* This file contains code for presenting F-Curves and other animation data
* in the UI (especially for use in the Animation Editors).
*
@@ -41,10 +46,10 @@
#include "DNA_anim_types.h"
-
-
#include "RNA_access.h"
+#include "ED_anim_api.h"
+
/* ----------------------- Getter functions ----------------------- */
/* Write into "name" buffer, the name of the property (retrieved using RNA from the curve's settings),
@@ -95,6 +100,8 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
* - as base, we use a custom name from the structs if one is available
* - however, if we're showing subdata of bones (probably there will be other exceptions later)
* need to include that info too since it gets confusing otherwise
+ * - if a pointer just refers to the ID-block, then don't repeat this info
+ * since this just introduces clutter
*/
if (strstr(fcu->rna_path, "bones") && strstr(fcu->rna_path, "constraints")) {
/* perform string 'chopping' to get "Bone Name : Constraint Name" */
@@ -109,7 +116,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
if (pchanName) MEM_freeN(pchanName);
if (constName) MEM_freeN(constName);
}
- else {
+ else if (ptr.data != ptr.id.data) {
PropertyRNA *nameprop= RNA_struct_name_property(ptr.type);
if (nameprop) {
/* this gets a string which will need to be freed */
@@ -140,7 +147,11 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
/* putting this all together into the buffer */
// XXX we need to check for invalid names...
- BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
+ // XXX the name length limit needs to be passed in or as some define
+ if (structname)
+ BLI_snprintf(name, 256, "%s%s (%s)", arrayname, propname, structname);
+ else
+ BLI_snprintf(name, 256, "%s%s", arrayname, propname);
/* free temp name if nameprop is set */
if (free_structname)
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 58dc5008959..732fc0bd267 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_markers.c
+ * \ingroup edanimation
+ */
+
+
#include <math.h>
#include "MEM_guardedalloc.h"
@@ -45,6 +50,7 @@
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -63,6 +69,7 @@
#include "ED_util.h"
#include "ED_numinput.h"
#include "ED_object.h"
+#include "ED_transform.h"
#include "ED_types.h"
/* ************* Marker API **************** */
@@ -109,6 +116,57 @@ ListBase *ED_animcontext_get_markers(const bAnimContext *ac)
/* --------------------------------- */
+/* Apply some transformation to markers after the fact
+ * < markers: list of markers to affect - this may or may not be the scene markers list, so don't assume anything
+ * < scene: current scene (for getting current frame)
+ * < mode: (TfmMode) transform mode that this transform is for
+ * < value: from the transform code, this is t->vec[0] (which is delta transform for grab/extend, and scale factor for scale)
+ * < side: (B/L/R) for 'extend' functionality, which side of current frame to use
+ */
+int ED_markers_post_apply_transform (ListBase *markers, Scene *scene, int mode, float value, char side)
+{
+ TimeMarker *marker;
+ float cfra = (float)CFRA;
+ int changed = 0;
+
+ /* sanity check */
+ if (markers == NULL)
+ return changed;
+
+ /* affect selected markers - it's unlikely that we will want to affect all in this way? */
+ for (marker = markers->first; marker; marker = marker->next) {
+ if (marker->flag & SELECT) {
+ switch (mode) {
+ case TFM_TIME_TRANSLATE:
+ case TFM_TIME_EXTEND:
+ {
+ /* apply delta if marker is on the right side of the current frame */
+ if ((side=='B') ||
+ (side=='L' && marker->frame < cfra) ||
+ (side=='R' && marker->frame >= cfra))
+ {
+ marker->frame += (int)floorf(value + 0.5f);
+ changed++;
+ }
+ }
+ break;
+
+ case TFM_TIME_SCALE:
+ {
+ /* rescale the distance between the marker and the current frame */
+ marker->frame= cfra + (int)floorf(((float)(marker->frame - cfra) * value) + 0.5f);
+ changed++;
+ }
+ break;
+ }
+ }
+ }
+
+ return changed;
+}
+
+/* --------------------------------- */
+
/* Get the marker that is closest to this point */
/* XXX for select, the min_dist should be small */
TimeMarker *ED_markers_find_nearest_marker (ListBase *markers, float x)
@@ -205,7 +263,7 @@ void ED_markers_get_minmax (ListBase *markers, short sel, float *first, float *l
/* --------------------------------- */
/* Adds a marker to list of cfra elems */
-void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
+static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only_sel)
{
CfraElem *ce, *cen;
@@ -264,6 +322,29 @@ TimeMarker *ED_markers_get_first_selected(ListBase *markers)
return NULL;
}
+/* --------------------------------- */
+
+/* Print debugging prints of list of markers
+ * BSI's: do NOT make static or put in if-defs as "unused code". That's too much trouble when we need to use for quick debuggging!
+ */
+void debug_markers_print_list(ListBase *markers)
+{
+ TimeMarker *marker;
+
+ if (markers == NULL) {
+ printf("No markers list to print debug for\n");
+ return;
+ }
+
+ printf("List of markers follows: -----\n");
+
+ for (marker = markers->first; marker; marker = marker->next) {
+ printf("\t'%s' on %d at %p with %d\n", marker->name, marker->frame, (void *)marker, marker->flag);
+ }
+
+ printf("End of list ------------------\n");
+}
+
/* ************* Marker Drawing ************ */
/* function to draw markers */
@@ -318,7 +399,6 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
UI_icon_draw(xpos*xscale-5.0f, 16.0f, icon_id);
- glBlendFunc(GL_ONE, GL_ZERO);
glDisable(GL_BLEND);
/* and the marker name too, shifted slightly to the top-right */
@@ -343,7 +423,7 @@ static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
}
#ifdef DURIAN_CAMERA_SWITCH
- if(marker->camera && marker->camera->restrictflag & OB_RESTRICT_RENDER) {
+ if(marker->camera && (marker->camera->restrictflag & OB_RESTRICT_RENDER)) {
float col[4];
glGetFloatv(GL_CURRENT_COLOR, col);
col[3]= 0.4;
@@ -386,9 +466,6 @@ void draw_markers_time(const bContext *C, int flag)
* primary operations of those editors.
*/
-/* maximum y-axis value (in region screen-space) that marker events should still be accepted for */
-#define ANIMEDIT_MARKER_YAXIS_MAX 40
-
/* ------------------------ */
/* special poll() which checks if there are selected markers first */
@@ -433,15 +510,7 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent
ScrArea *sa = CTX_wm_area(C);
int retval = OPERATOR_PASS_THROUGH;
- /* only timeline view doesn't need calling-location validation as it's the only dedicated view */
- if (sa->spacetype != SPACE_TIME) {
- /* restrict y-values to within ANIMEDIT_MARKER_YAXIS_MAX of the view's vertical extents, including scrollbars */
- if (evt->mval[1] > ANIMEDIT_MARKER_YAXIS_MAX) {
- /* not ok... "pass-through" to let normal editor's operators have a chance at tackling this event... */
- //printf("MARKER-WRAPPER-DEBUG: event mval[1] = %d, so over accepted tolerance\n", evt->mval[1]);
- return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH;
- }
- }
+ /* removed check for Y coord of event, keymap has bounbox now */
/* allow operator to run now */
if (invoke_func)
@@ -496,7 +565,7 @@ static int ed_marker_add(bContext *C, wmOperator *UNUSED(op))
marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
marker->flag= SELECT;
marker->frame= frame;
- sprintf(marker->name, "F_%02d", frame); // XXX - temp code only
+ BLI_snprintf(marker->name, sizeof(marker->name), "F_%02d", frame); // XXX - temp code only
BLI_addtail(markers, marker);
WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
@@ -649,7 +718,7 @@ static void ed_marker_move_apply(wmOperator *op)
}
/* only for modal */
-static void ed_marker_move_cancel(bContext *C, wmOperator *op)
+static int ed_marker_move_cancel(bContext *C, wmOperator *op)
{
RNA_int_set(op->ptr, "frames", 0);
ed_marker_move_apply(op);
@@ -657,6 +726,8 @@ static void ed_marker_move_cancel(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
+
+ return OPERATOR_CANCELLED;
}
@@ -675,18 +746,24 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
ed_marker_move_cancel(C, op);
return OPERATOR_CANCELLED;
+ case RIGHTMOUSE:
+ /* press = user manually demands transform to be cancelled */
+ if (evt->val == KM_PRESS) {
+ ed_marker_move_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ /* else continue; <--- see if release event should be caught for tweak-end */
+
case RETKEY:
case PADENTER:
case LEFTMOUSE:
case MIDDLEMOUSE:
- case RIGHTMOUSE:
if (WM_modal_tweak_exit(evt, mm->event_type)) {
ed_marker_move_exit(C, op);
WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
return OPERATOR_FINISHED;
}
-
break;
case MOUSEMOVE:
if (hasNumInput(&mm->num))
@@ -724,19 +801,19 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
SpaceTime *stime= (SpaceTime *)mm->slink;
if (stime->flag & TIME_DRAWFRAMES)
- sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
+ BLI_snprintf(str, sizeof(str), "Marker %d offset %d", selmarker->frame, offs);
else
- sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
+ BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
}
else if (mm->slink->spacetype == SPACE_ACTION) {
SpaceAction *saction= (SpaceAction *)mm->slink;
if (saction->flag & SACTION_DRAWTIME)
- sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
+ BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
else
- sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
+ BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
}
else {
- sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
+ BLI_snprintf(str, sizeof(str), "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
}
}
else {
@@ -744,19 +821,19 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
SpaceTime *stime= (SpaceTime *)mm->slink;
if (stime->flag & TIME_DRAWFRAMES)
- sprintf(str, "Marker offset %d ", offs);
+ BLI_snprintf(str, sizeof(str), "Marker offset %d ", offs);
else
- sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
+ BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs));
}
else if (mm->slink->spacetype == SPACE_ACTION) {
SpaceAction *saction= (SpaceAction *)mm->slink;
if (saction->flag & SACTION_DRAWTIME)
- sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
+ BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", FRA2TIME(offs));
else
- sprintf(str, "Marker offset %.2f ", (double)(offs));
+ BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs));
}
else {
- sprintf(str, "Marker offset %.2f ", (double)(offs));
+ BLI_snprintf(str, sizeof(str), "Marker offset %.2f ", (double)(offs));
}
}
@@ -779,7 +856,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
ed_marker_move_apply(op);
// ed_marker_header_update(C, op, str, (int)vec[0]);
// strcat(str, str_tx);
- sprintf(str, "Marker offset %s", str_tx);
+ BLI_snprintf(str, sizeof(str), "Marker offset %s", str_tx);
ED_area_headerprint(CTX_wm_area(C), str);
WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
@@ -812,6 +889,7 @@ static void MARKER_OT_move(wmOperatorType *ot)
ot->invoke= ed_marker_move_invoke_wrapper;
ot->modal= ed_marker_move_modal;
ot->poll= ed_markers_poll_selected_markers;
+ ot->cancel= ed_marker_move_cancel;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
@@ -868,6 +946,7 @@ static void ed_marker_duplicate_apply(bContext *C)
#endif
/* new marker is added to the begining of list */
+ // FIXME: bad ordering!
BLI_addhead(markers, newmarker);
}
}
@@ -905,6 +984,7 @@ static void MARKER_OT_duplicate(wmOperatorType *ot)
ot->invoke= ed_marker_duplicate_invoke_wrapper;
ot->modal= ed_marker_move_modal;
ot->poll= ed_markers_poll_selected_markers;
+ ot->cancel= ed_marker_move_cancel;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
@@ -996,8 +1076,8 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera)
WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
- /* allowing tweaks */
- return OPERATOR_PASS_THROUGH;
+ /* allowing tweaks, but needs OPERATOR_FINISHED, otherwise renaming fails... [#25987] */
+ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
}
static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
@@ -1110,6 +1190,7 @@ static void MARKER_OT_select_border(wmOperatorType *ot)
ot->exec= ed_marker_border_select_exec;
ot->invoke= ed_marker_select_border_invoke_wrapper;
ot->modal= WM_border_select_modal;
+ ot->cancel= WM_border_select_cancel;
ot->poll= ed_markers_poll_markers_exist;
@@ -1336,7 +1417,9 @@ static void MARKER_OT_make_links_scene(wmOperatorType *ot)
static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op))
{
+ bScreen *sc= CTX_wm_screen(C);
Scene *scene= CTX_data_scene(C);
+ Object *ob = CTX_data_active_object(C);
ListBase *markers= ED_context_get_markers(C);
TimeMarker *marker;
@@ -1344,10 +1427,15 @@ static int ed_marker_camera_bind_exec(bContext *C, wmOperator *UNUSED(op))
if(marker == NULL)
return OPERATOR_CANCELLED;
- marker->camera= scene->camera;
+ marker->camera= ob;
+
+ /* camera may have changes */
+ scene_camera_switch_update(scene);
+ BKE_screen_view3d_scene_sync(sc);
WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL);
WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL);
+ WM_event_add_notifier(C, NC_SCENE|NA_EDITED, scene); /* so we get view3d redraws */
return OPERATOR_FINISHED;
}
@@ -1420,3 +1508,14 @@ void ED_marker_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MARKER_OT_camera_bind", BKEY, KM_PRESS, KM_CTRL, 0);
#endif
}
+
+/* to be called from animation editor keymaps, see note below */
+void ED_marker_keymap_animedit_conflictfree(wmKeyMap *keymap)
+{
+ /* duplicate of some marker-hotkeys but without the bounds checking
+ * since these are handy to be able to do unrestricted and won't conflict
+ * with primary function hotkeys (Usability tweak [#27469])
+ */
+ WM_keymap_add_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0);
+}
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 6b0fa30b096..7a94a21d41e 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/anim_ops.c
+ * \ingroup edanimation
+ */
+
+
#include <stdlib.h>
#include <math.h>
@@ -37,6 +42,7 @@
#include "DNA_scene_types.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_sound.h"
#include "UI_view2d.h"
@@ -47,6 +53,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_anim_api.h"
#include "ED_screen.h"
#include "anim_intern.h"
@@ -58,6 +65,9 @@ static int change_frame_poll(bContext *C)
{
ScrArea *curarea= CTX_wm_area(C);
+ /* XXX temp? prevent changes during render */
+ if(G.rendering) return 0;
+
/* as long as there is an active area, and it isn't a Graph Editor
* (since the Graph Editor has its own version which does extra stuff),
* we're fine
@@ -97,14 +107,9 @@ static int frame_from_event(bContext *C, wmEvent *event)
{
ARegion *region= CTX_wm_region(C);
float viewx;
- int x, y;
-
- /* convert screen coordinates to region coordinates */
- x= event->x - region->winrct.xmin;
- y= event->y - region->winrct.ymin;
-
+
/* convert from region coordinates to View2D 'tot' space */
- UI_view2d_region_to_view(&region->v2d, x, y, &viewx, NULL);
+ UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &viewx, NULL);
/* round result to nearest int (frames are ints!) */
return (int)floor(viewx+0.5f);
@@ -153,7 +158,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-void ANIM_OT_change_frame(wmOperatorType *ot)
+static void ANIM_OT_change_frame(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Change frame";
@@ -194,8 +199,8 @@ static int previewrange_define_exec(bContext *C, wmOperator *op)
* - must clamp within allowable limits
* - end must not be before start (though this won't occur most of the time)
*/
- if (sfra < 1) sfra = 1.0f;
- if (efra < 1) efra = 1.0f;
+ FRAMENUMBER_MIN_CLAMP(sfra);
+ FRAMENUMBER_MIN_CLAMP(efra);
if (efra < sfra) efra= sfra;
scene->r.flag |= SCER_PRV_RANGE;
@@ -208,7 +213,7 @@ static int previewrange_define_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ANIM_OT_previewrange_set(wmOperatorType *ot)
+static void ANIM_OT_previewrange_set(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Set Preview Range";
@@ -219,6 +224,7 @@ void ANIM_OT_previewrange_set(wmOperatorType *ot)
ot->invoke= WM_border_select_invoke;
ot->exec= previewrange_define_exec;
ot->modal= WM_border_select_modal;
+ ot->cancel= WM_border_select_cancel;
ot->poll= ED_operator_animview_active;
@@ -255,7 +261,7 @@ static int previewrange_clear_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void ANIM_OT_previewrange_clear(wmOperatorType *ot)
+static void ANIM_OT_previewrange_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Clear Preview Range";
@@ -323,7 +329,7 @@ static int toggle_time_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-void ANIM_OT_time_toggle(wmOperatorType *ot)
+static void ANIM_OT_time_toggle(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Toggle Frames/Seconds";
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 8d74e7b1b59..c9e422baa3e 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
+/** \file blender/editors/animation/drivers.c
+ * \ingroup edanimation
+ */
+
#include <stdio.h>
#include <string.h>
@@ -60,6 +65,11 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "anim_intern.h"
+
+/* called by WM */
+void free_anim_drivers_copybuf (void);
+
/* ************************************************** */
/* Animation Data Validation */
@@ -475,7 +485,7 @@ static char *get_driver_path_hack (bContext *C, PointerRNA *ptr, PropertyRNA *pr
static int add_driver_button_exec (bContext *C, wmOperator *op)
{
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
PropertyRNA *prop= NULL;
short success= 0;
int index, all= RNA_boolean_get(op->ptr, "all");
@@ -531,7 +541,7 @@ void ANIM_OT_driver_button_add (wmOperatorType *ot)
static int remove_driver_button_exec (bContext *C, wmOperator *op)
{
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
PropertyRNA *prop= NULL;
short success= 0;
int index, all= RNA_boolean_get(op->ptr, "all");
@@ -583,7 +593,7 @@ void ANIM_OT_driver_button_remove (wmOperatorType *ot)
static int copy_driver_button_exec (bContext *C, wmOperator *op)
{
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
PropertyRNA *prop= NULL;
short success= 0;
int index;
@@ -627,7 +637,7 @@ void ANIM_OT_copy_driver_button (wmOperatorType *ot)
static int paste_driver_button_exec (bContext *C, wmOperator *op)
{
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
PropertyRNA *prop= NULL;
short success= 0;
int index;
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index b47fea58633..8197d6b25dd 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/fmodifier_ui.c
+ * \ingroup edanimation
+ */
+
+
/* User-Interface Stuff for F-Modifiers:
* This file defines the (C-Coded) templates + editing callbacks needed
* by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
@@ -53,10 +58,12 @@
#include "RNA_access.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
+#include "ED_anim_api.h"
+#include "ED_util.h"
+
/* ********************************************** */
/* UI STUFF */
@@ -93,6 +100,8 @@ static void delete_fmodifier_cb (bContext *C, void *fmods_v, void *fcm_v)
/* remove the given F-Modifier from the active modifier-stack */
remove_fmodifier(modifiers, fcm);
+
+ ED_undo_push(C, "Delete F-Curve Modifier");
/* send notifiers */
// XXX for now, this is the only way to get updates in all the right places... but would be nice to have a special one in this case
@@ -226,14 +235,14 @@ static void draw_modifier__fn_generator(uiLayout *layout, ID *id, FModifier *fcm
/* add the settings */
col= uiLayoutColumn(layout, 1);
- uiItemR(col, &ptr, "function_type", 0, "", ICON_NULL);
- uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "function_type", 0, "", ICON_NONE);
+ uiItemR(col, &ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
col= uiLayoutColumn(layout, 0); // no grouping for now
- uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "amplitude", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "phase_multiplier", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "phase_offset", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "value_offset", 0, NULL, ICON_NONE);
}
/* --------------- */
@@ -254,15 +263,15 @@ static void draw_modifier__cycles(uiLayout *layout, ID *id, FModifier *fcm, shor
/* before range */
col= uiLayoutColumn(split, 1);
- uiItemL(col, "Before:", ICON_NULL);
- uiItemR(col, &ptr, "mode_before", 0, "", ICON_NULL);
- uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NULL);
+ uiItemL(col, "Before:", ICON_NONE);
+ uiItemR(col, &ptr, "mode_before", 0, "", ICON_NONE);
+ uiItemR(col, &ptr, "cycles_before", 0, NULL, ICON_NONE);
/* after range */
col= uiLayoutColumn(split, 1);
- uiItemL(col, "After:", ICON_NULL);
- uiItemR(col, &ptr, "mode_after", 0, "", ICON_NULL);
- uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NULL);
+ uiItemL(col, "After:", ICON_NONE);
+ uiItemR(col, &ptr, "mode_after", 0, "", ICON_NONE);
+ uiItemR(col, &ptr, "cycles_after", 0, NULL, ICON_NONE);
}
/* --------------- */
@@ -277,25 +286,25 @@ static void draw_modifier__noise(uiLayout *layout, ID *id, FModifier *fcm, short
RNA_pointer_create(id, &RNA_FModifierNoise, fcm, &ptr);
/* blending mode */
- uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NULL);
+ uiItemR(layout, &ptr, "blend_type", 0, NULL, ICON_NONE);
/* split into 2 columns */
split= uiLayoutSplit(layout, 0.5f, 0);
/* col 1 */
col= uiLayoutColumn(split, 0);
- uiItemR(col, &ptr, "scale", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "strength", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "scale", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "strength", 0, NULL, ICON_NONE);
/* col 2 */
col= uiLayoutColumn(split, 0);
- uiItemR(col, &ptr, "phase", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "depth", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "phase", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "depth", 0, NULL, ICON_NONE);
}
/* --------------- */
-#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001
+#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f
/* Binary search algorithm for finding where to insert Envelope Data Point.
* Returns the index to insert at (data already at that index will be offset if replace is 0)
@@ -437,9 +446,9 @@ static void fmod_envelope_deletepoint_cb (bContext *UNUSED(C), void *fcm_dv, voi
if (env->totvert > 1) {
/* allocate a new smaller array */
fedn= MEM_callocN(sizeof(FCM_EnvelopeData)*(env->totvert-1), "FCM_EnvelopeData");
-
- memcpy(fedn, &env->data, sizeof(FCM_EnvelopeData)*(index));
- memcpy(&fedn[index], &env->data[index+1], sizeof(FCM_EnvelopeData)*(env->totvert-index-1));
+
+ memcpy(fedn, env->data, sizeof(FCM_EnvelopeData)*(index));
+ memcpy(fedn + index, env->data + (index + 1), sizeof(FCM_EnvelopeData)*((env->totvert - index)-1));
/* free old array, and set the new */
MEM_freeN(env->data);
@@ -448,8 +457,10 @@ static void fmod_envelope_deletepoint_cb (bContext *UNUSED(C), void *fcm_dv, voi
}
else {
/* just free array, since the only vert was deleted */
- if (env->data)
+ if (env->data) {
MEM_freeN(env->data);
+ env->data= NULL;
+ }
env->totvert= 0;
}
}
@@ -470,12 +481,12 @@ static void draw_modifier__envelope(uiLayout *layout, ID *id, FModifier *fcm, sh
/* general settings */
col= uiLayoutColumn(layout, 1);
- uiItemL(col, "Envelope:", ICON_NULL);
- uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NULL);
+ uiItemL(col, "Envelope:", ICON_NONE);
+ uiItemR(col, &ptr, "reference_value", 0, NULL, ICON_NONE);
row= uiLayoutRow(col, 1);
- uiItemR(row, &ptr, "default_min", 0, "Min", ICON_NULL);
- uiItemR(row, &ptr, "default_max", 0, "Max", ICON_NULL);
+ uiItemR(row, &ptr, "default_min", 0, "Min", ICON_NONE);
+ uiItemR(row, &ptr, "default_max", 0, "Max", ICON_NONE);
/* control points header */
// TODO: move this control-point control stuff to using the new special widgets for lists
@@ -527,13 +538,13 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor
/* x-minimum */
col= uiLayoutColumn(split, 1);
- uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "use_min_x", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "min_x", 0, NULL, ICON_NONE);
/* y-minimum*/
col= uiLayoutColumn(split, 1);
- uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "use_min_y", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "min_y", 0, NULL, ICON_NONE);
}
/* row 2: maximum */
@@ -545,13 +556,13 @@ static void draw_modifier__limits(uiLayout *layout, ID *id, FModifier *fcm, shor
/* x-minimum */
col= uiLayoutColumn(split, 1);
- uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "use_max_x", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "max_x", 0, NULL, ICON_NONE);
/* y-minimum*/
col= uiLayoutColumn(split, 1);
- uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "use_max_y", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "max_y", 0, NULL, ICON_NONE);
}
}
@@ -568,24 +579,24 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho
/* block 1: "stepping" settings */
col= uiLayoutColumn(layout, 0);
- uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NULL);
- uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "frame_step", 0, NULL, ICON_NONE);
+ uiItemR(col, &ptr, "frame_offset", 0, NULL, ICON_NONE);
/* block 2: start range settings */
col= uiLayoutColumn(layout, 1);
- uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "use_frame_start", 0, NULL, ICON_NONE);
subcol = uiLayoutColumn(col, 1);
uiLayoutSetActive(subcol, RNA_boolean_get(&ptr, "use_frame_start"));
- uiItemR(subcol, &ptr, "frame_start", 0, NULL, ICON_NULL);
+ uiItemR(subcol, &ptr, "frame_start", 0, NULL, ICON_NONE);
/* block 3: end range settings */
col= uiLayoutColumn(layout, 1);
- uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NULL);
+ uiItemR(col, &ptr, "use_frame_end", 0, NULL, ICON_NONE);
subcol = uiLayoutColumn(col, 1);
uiLayoutSetActive(subcol, RNA_boolean_get(&ptr, "use_frame_end"));
- uiItemR(subcol, &ptr, "frame_end", 0, NULL, ICON_NULL);
+ uiItemR(subcol, &ptr, "frame_end", 0, NULL, ICON_NONE);
}
/* --------------- */
@@ -593,7 +604,7 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- uiLayout *box, *row, *subrow;
+ uiLayout *box, *row, *subrow, *col;
uiBlock *block;
uiBut *but;
short width= 314;
@@ -611,30 +622,30 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
block= uiLayoutGetBlock(row); // err...
/* left-align -------------------------------------------- */
- subrow= uiLayoutRow(row, 0);
+ subrow= uiLayoutRow(row, 1);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
uiBlockSetEmboss(block, UI_EMBOSSN);
/* expand */
- uiItemR(subrow, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NULL);
+ uiItemR(subrow, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
/* checkbox for 'active' status (for now) */
- uiItemR(subrow, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NULL);
+ uiItemR(subrow, &ptr, "active", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
/* name */
if (fmi)
- uiItemL(subrow, fmi->name, ICON_NULL);
+ uiItemL(subrow, fmi->name, ICON_NONE);
else
- uiItemL(subrow, "<Unknown Modifier>", ICON_NULL);
+ uiItemL(subrow, "<Unknown Modifier>", ICON_NONE);
/* right-align ------------------------------------------- */
- subrow= uiLayoutRow(row, 0);
+ subrow= uiLayoutRow(row, 1);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
/* 'mute' button */
- uiItemR(subrow, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NULL);
+ uiItemR(subrow, &ptr, "mute", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -683,6 +694,44 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
default: /* unknown type */
break;
}
+
+ /* one last panel below this: FModifier range */
+ // TODO: experiment with placement of this
+ {
+ box = uiLayoutBox(layout);
+
+ /* restricted range ----------------------------------------------------- */
+ col = uiLayoutColumn(box, 1);
+
+ /* top row: use restricted range */
+ row= uiLayoutRow(col, 1);
+ uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
+ /* second row: settings */
+ row = uiLayoutRow(col, 1);
+
+ uiItemR(row, &ptr, "frame_start", 0, "Start", ICON_NONE);
+ uiItemR(row, &ptr, "frame_end", 0, "End", ICON_NONE);
+
+ /* third row: blending influence */
+ row = uiLayoutRow(col, 1);
+
+ uiItemR(row, &ptr, "blend_in", 0, "In", ICON_NONE);
+ uiItemR(row, &ptr, "blend_out", 0, "Out", ICON_NONE);
+ }
+
+ /* influence -------------------------------------------------------------- */
+ col = uiLayoutColumn(box, 1);
+
+ /* top row: use influence */
+ uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
+ /* second row: influence value */
+ uiItemR(col, &ptr, "influence", 0, NULL, ICON_NONE);
+ }
+ }
}
}
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index c1958064431..b774bc947e4 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -27,6 +27,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/keyframes_draw.c
+ * \ingroup edanimation
+ */
+
+
/* System includes ----------------------------------------------------- */
#include <math.h>
@@ -75,7 +80,7 @@
/* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
/* Comparator callback used for ActKeyColumns and cframe float-value pointer */
-// NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes
+/* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
short compare_ak_cfraPtr (void *node, void *data)
{
ActKeyColumn *ak= (ActKeyColumn *)node;
@@ -306,6 +311,23 @@ static BezTriple *abk_get_bezt_with_value (ActBeztColumn *abk, float value)
/* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
+/* Comparator callback used for ActKeyBlock and cframe float-value pointer */
+/* NOTE: this is exported to other modules that use the ActKeyBlocks for finding long-keyframes */
+short compare_ab_cfraPtr (void *node, void *data)
+{
+ ActKeyBlock *ab= (ActKeyBlock *)node;
+ float *cframe= data;
+
+ if (*cframe < ab->start)
+ return -1;
+ else if (*cframe > ab->start)
+ return 1;
+ else
+ return 0;
+}
+
+/* --------------- */
+
/* Create a ActKeyColumn for a pair of BezTriples */
static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
{
@@ -338,9 +360,9 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, DLRBT_Tree *beztTree,
* -> secondly, handles which control that section of the curve must be constant
*/
if ((!prev) || (!beztn)) return;
- if (IS_EQ(beztn->vec[1][1], prev->vec[1][1])==0) return;
- if (IS_EQ(beztn->vec[1][1], beztn->vec[0][1])==0) return;
- if (IS_EQ(prev->vec[1][1], prev->vec[2][1])==0) return;
+ if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])==0) return;
+ if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1])==0) return;
+ if (IS_EQF(prev->vec[1][1], prev->vec[2][1])==0) return;
/* if there are no blocks already, just add as root */
@@ -350,7 +372,7 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, DLRBT_Tree *beztTree,
blocks->root= (DLRBT_Node *)new_ab;
}
else {
- ActKeyBlock *ab, *abp=NULL, *abn=NULL;
+ ActKeyBlock *ab, *abn=NULL;
/* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
* Note: we can't search from end to try to optimise this as it causes errors there's
@@ -360,7 +382,7 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, DLRBT_Tree *beztTree,
// A|--------------|A ______________ B|--------------|B
// A|------------------------------------------------|A
// A|----|A|---|A|-----------------------------------|A
- for (ab= blocks->root; ab; abp= ab, ab= abn) {
+ for (ab= blocks->root; ab; ab= abn) {
/* check if this is a match, or whether we go left or right */
if (ab->start == prev->vec[1][0]) {
/* set selection status and 'touched' status */
@@ -435,6 +457,33 @@ static void set_touched_actkeyblock (ActKeyBlock *ab)
set_touched_actkeyblock(ab->right);
}
+/* --------- */
+
+/* Checks if ActKeyBlock should exist... */
+short actkeyblock_is_valid (ActKeyBlock *ab, DLRBT_Tree *keys)
+{
+ ActKeyColumn *ak;
+ short startCurves, endCurves, totCurves;
+
+ /* check that block is valid */
+ if (ab == NULL)
+ return 0;
+
+ /* find out how many curves occur at each keyframe */
+ ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
+ startCurves = (ak)? ak->totcurve: 0;
+
+ ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
+ endCurves = (ak)? ak->totcurve: 0;
+
+ /* only draw keyblock if it appears in at all of the keyframes at lowest end */
+ if (!startCurves && !endCurves)
+ return 0;
+
+ totCurves = (startCurves>endCurves)? endCurves: startCurves;
+ return (ab->totcurve >= totCurves);
+}
+
/* *************************** Keyframe Drawing *************************** */
/* coordinates for diamond shape */
@@ -554,22 +603,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
/* draw keyblocks */
if (blocks) {
for (ab= blocks->first; ab; ab= ab->next) {
- short startCurves, endCurves, totCurves;
-
- /* find out how many curves occur at each keyframe */
- ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
- startCurves = (ak)? ak->totcurve: 0;
-
- ak= (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
- endCurves = (ak)? ak->totcurve: 0;
-
- /* only draw keyblock if it appears in at all of the keyframes at lowest end */
- if (!startCurves && !endCurves)
- continue;
- else
- totCurves = (startCurves>endCurves)? endCurves: startCurves;
-
- if (ab->totcurve >= totCurves) {
+ if (actkeyblock_is_valid(ab, keys)) {
/* draw block */
if (ab->sel)
UI_ThemeColor4(TH_STRIP_SELECT);
@@ -739,7 +773,7 @@ void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
int filter;
/* get F-Curves to take keyframes from */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ filter= ANIMFILTER_DATA_VISIBLE; // curves only
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through each F-Curve, grabbing the keyframes */
@@ -752,158 +786,79 @@ void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
{
- if (sce) {
- AnimData *adt;
- int filterflag;
-
- /* get filterflag */
- if (ads)
- filterflag= ads->filterflag;
- else
- filterflag= 0;
-
- /* scene animdata */
- if ((sce->adt) && !(filterflag & ADS_FILTER_NOSCE)) {
- adt= sce->adt;
-
- if (adt->action)
- action_to_keylist(adt, adt->action, keys, blocks);
- }
-
- /* world animdata */
- if ((sce->world) && (sce->world->adt) && !(filterflag & ADS_FILTER_NOWOR)) {
- adt= sce->world->adt;
-
- if (adt->action)
- action_to_keylist(adt, adt->action, keys, blocks);
- }
-
- /* nodetree animdata */
- if ((sce->nodetree) && (sce->nodetree->adt) && !(filterflag & ADS_FILTER_NONTREE)) {
- adt= sce->nodetree->adt;
-
- if (adt->action)
- action_to_keylist(adt, adt->action, keys, blocks);
- }
- }
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ bAnimListElem dummychan = {0};
+
+ if (sce == NULL)
+ return;
+
+ /* create a dummy wrapper data to work with */
+ dummychan.type = ANIMTYPE_SCENE;
+ dummychan.data = sce;
+ dummychan.id = &sce->id;
+ dummychan.adt = sce->adt;
+
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
+
+ /* get F-Curves to take keyframes from */
+ filter= ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through each F-Curve, grabbing the keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
+
+ BLI_freelistN(&anim_data);
}
void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
-{
- Key *key= ob_get_key(ob);
- int filterflag= (ads)? ads->filterflag : 0;
+{
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+
+ bAnimListElem dummychan = {0};
+ Base dummybase = {0};
- /* sanity check */
if (ob == NULL)
return;
-
- /* Add action keyframes */
- if (ob->adt && ob->adt->action)
- action_to_keylist(ob->adt, ob->adt->action, keys, blocks);
- /* Add shapekey keyframes (only if dopesheet allows, if it is available) */
- if ((key && key->adt && key->adt->action) && !(filterflag & ADS_FILTER_NOSHAPEKEYS))
- action_to_keylist(key->adt, key->adt->action, keys, blocks);
+ /* create a dummy wrapper data to work with */
+ dummybase.object = ob;
- /* Add material keyframes */
- if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
- int a;
-
- for (a=1; a <= ob->totcol; a++) {
- Material *ma= give_current_material(ob, a);
-
- /* there might not be a material */
- if (ELEM(NULL, ma, ma->adt))
- continue;
-
- /* add material's data */
- action_to_keylist(ma->adt, ma->adt->action, keys, blocks);
-
- // TODO: textures...
- }
- }
+ dummychan.type = ANIMTYPE_OBJECT;
+ dummychan.data = &dummybase;
+ dummychan.id = &ob->id;
+ dummychan.adt = ob->adt;
- /* Add object data keyframes */
- switch (ob->type) {
- case OB_CAMERA: /* ------- Camera ------------ */
- {
- Camera *ca= (Camera *)ob->data;
-
- if ((ca->adt) && !(filterflag & ADS_FILTER_NOCAM))
- action_to_keylist(ca->adt, ca->adt->action, keys, blocks);
- }
- break;
- case OB_LAMP: /* ---------- Lamp ----------- */
- {
- Lamp *la= (Lamp *)ob->data;
-
- if ((la->adt) && !(filterflag & ADS_FILTER_NOLAM))
- action_to_keylist(la->adt, la->adt->action, keys, blocks);
- }
- break;
- case OB_CURVE: /* ------- Curve ---------- */
- case OB_SURF: /* ------- Nurbs Surface ---------- */
- case OB_FONT: /* ------- Text Curve ---------- */
- {
- Curve *cu= (Curve *)ob->data;
-
- if ((cu->adt) && !(filterflag & ADS_FILTER_NOCUR))
- action_to_keylist(cu->adt, cu->adt->action, keys, blocks);
- }
- break;
- case OB_MBALL: /* ------- MetaBall ---------- */
- {
- MetaBall *mb= (MetaBall *)ob->data;
-
- if ((mb->adt) && !(filterflag & ADS_FILTER_NOMBA))
- action_to_keylist(mb->adt, mb->adt->action, keys, blocks);
- }
- break;
- case OB_ARMATURE: /* ------- Armature ---------- */
- {
- bArmature *arm= (bArmature *)ob->data;
-
- if ((arm->adt) && !(filterflag & ADS_FILTER_NOARM))
- action_to_keylist(arm->adt, arm->adt->action, keys, blocks);
- }
- break;
- case OB_MESH: /* ------- Mesh ---------- */
- {
- Mesh *me= (Mesh *)ob->data;
-
- if ((me->adt) && !(filterflag & ADS_FILTER_NOMESH))
- action_to_keylist(me->adt, me->adt->action, keys, blocks);
- }
- break;
- case OB_LATTICE: /* ------- Lattice ---------- */
- {
- Lattice *lt= (Lattice *)ob->data;
-
- if ((lt->adt) && !(filterflag & ADS_FILTER_NOLAT))
- action_to_keylist(lt->adt, lt->adt->action, keys, blocks);
- }
- break;
- }
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
- /* Add Particle System Keyframes */
- if ((ob->particlesystem.first) && !(filterflag & ADS_FILTER_NOPART)) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for(; psys; psys=psys->next) {
- if (ELEM(NULL, psys->part, psys->part->adt))
- continue;
- else
- action_to_keylist(psys->part->adt, psys->part->adt->action, keys, blocks);
- }
- }
+ /* get F-Curves to take keyframes from */
+ filter= ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through each F-Curve, grabbing the keyframes */
+ for (ale= anim_data.first; ale; ale= ale->next)
+ fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
+
+ BLI_freelistN(&anim_data);
}
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
{
DLRBT_Tree *beztTree = NULL;
BezTriple *bezt;
- int v;
-
+ unsigned int v;
+
if (fcu && fcu->totvert && fcu->bezt) {
/* apply NLA-mapping (if applicable) */
if (adt)
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index e9a2c1bdc06..9f3d40a5709 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -24,6 +24,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/keyframes_edit.c
+ * \ingroup edanimation
+ */
+
+
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -90,7 +95,7 @@ short ANIM_fcurve_keyframes_loop(KeyframeEditData *ked, FCurve *fcu, KeyframeEdi
{
BezTriple *bezt;
short ok = 0;
- int i;
+ unsigned int i;
/* sanity check */
if (ELEM(NULL, fcu, fcu->bezt))
@@ -192,196 +197,95 @@ static short act_keyframes_loop(KeyframeEditData *ked, bAction *act, KeyframeEdi
return 0;
}
-/* This function is used to loop over the keyframe data of an AnimData block */
-static short adt_keyframes_loop(KeyframeEditData *ked, AnimData *adt, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag)
-{
- /* sanity check */
- if (adt == NULL)
- return 0;
-
- /* drivers or actions? */
- if (filterflag & ADS_FILTER_ONLYDRIVERS) {
- FCurve *fcu;
-
- /* just loop through all F-Curves acting as Drivers */
- for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
- if (ANIM_fcurve_keyframes_loop(ked, fcu, key_ok, key_cb, fcu_cb))
- return 1;
- }
- }
- else if (adt->action) {
- /* call the function for actions */
- if (act_keyframes_loop(ked, adt->action, key_ok, key_cb, fcu_cb))
- return 1;
- }
-
- return 0;
-}
-
/* This function is used to loop over the keyframe data in an Object */
-static short ob_keyframes_loop(KeyframeEditData *ked, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag)
+static short ob_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Object *ob, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
- Key *key= ob_get_key(ob);
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int ret=0;
+
+ bAnimListElem dummychan = {0};
+ Base dummybase = {0};
- /* sanity check */
if (ob == NULL)
return 0;
- /* firstly, Object's own AnimData */
- if (ob->adt) {
- if (adt_keyframes_loop(ked, ob->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
+ /* create a dummy wrapper data to work with */
+ dummybase.object = ob;
- /* shapekeys */
- if ((key && key->adt) && !(filterflag & ADS_FILTER_NOSHAPEKEYS)) {
- if (adt_keyframes_loop(ked, key->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
-
- /* Add material keyframes */
- if ((ob->totcol) && !(filterflag & ADS_FILTER_NOMAT)) {
- int a;
-
- for (a=1; a <= ob->totcol; a++) {
- Material *ma= give_current_material(ob, a);
-
- /* there might not be a material */
- if (ELEM(NULL, ma, ma->adt))
- continue;
-
- /* add material's data */
- if (adt_keyframes_loop(ked, ma->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
+ dummychan.type = ANIMTYPE_OBJECT;
+ dummychan.data = &dummybase;
+ dummychan.id = &ob->id;
+ dummychan.adt = ob->adt;
- /* Add object data keyframes */
- switch (ob->type) {
- case OB_CAMERA: /* ------- Camera ------------ */
- {
- Camera *ca= (Camera *)ob->data;
-
- if ((ca->adt) && !(filterflag & ADS_FILTER_NOCAM)) {
- if (adt_keyframes_loop(ked, ca->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
- break;
- case OB_LAMP: /* ---------- Lamp ----------- */
- {
- Lamp *la= (Lamp *)ob->data;
-
- if ((la->adt) && !(filterflag & ADS_FILTER_NOLAM)) {
- if (adt_keyframes_loop(ked, la->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
- break;
- case OB_CURVE: /* ------- Curve ---------- */
- case OB_SURF: /* ------- Nurbs Surface ---------- */
- case OB_FONT: /* ------- Text Curve ---------- */
- {
- Curve *cu= (Curve *)ob->data;
-
- if ((cu->adt) && !(filterflag & ADS_FILTER_NOCUR)) {
- if (adt_keyframes_loop(ked, cu->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
- break;
- case OB_MBALL: /* ------- MetaBall ---------- */
- {
- MetaBall *mb= (MetaBall *)ob->data;
-
- if ((mb->adt) && !(filterflag & ADS_FILTER_NOMBA)) {
- if (adt_keyframes_loop(ked, mb->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
- break;
- case OB_ARMATURE: /* ------- Armature ---------- */
- {
- bArmature *arm= (bArmature *)ob->data;
-
- if ((arm->adt) && !(filterflag & ADS_FILTER_NOARM)) {
- if (adt_keyframes_loop(ked, arm->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
- break;
- case OB_MESH: /* ------- Mesh ---------- */
- {
- Mesh *me= (Mesh *)ob->data;
-
- if ((me->adt) && !(filterflag & ADS_FILTER_NOMESH)) {
- if (adt_keyframes_loop(ked, me->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
+
+ /* get F-Curves to take keyframes from */
+ filter= ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (ANIM_fcurve_keyframes_loop(ked, (FCurve*)ale->data, key_ok, key_cb, fcu_cb)) {
+ ret = 1;
break;
- case OB_LATTICE: /* ---- Lattice ------ */
- {
- Lattice *lt= (Lattice *)ob->data;
-
- if ((lt->adt) && !(filterflag & ADS_FILTER_NOLAT)) {
- if (adt_keyframes_loop(ked, lt->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
}
- break;
}
- /* Add Particle System Keyframes */
- if ((ob->particlesystem.first) && !(filterflag & ADS_FILTER_NOPART)) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for(; psys; psys=psys->next) {
- if (ELEM(NULL, psys->part, psys->part->adt))
- continue;
-
- if (adt_keyframes_loop(ked, psys->part->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
- }
+ BLI_freelistN(&anim_data);
- return 0;
+ /* return return code - defaults to zero if nothing happened */
+ return ret;
}
/* This function is used to loop over the keyframe data in a Scene */
-static short scene_keyframes_loop(KeyframeEditData *ked, Scene *sce, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag)
+static short scene_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, Scene *sce, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
- World *wo= (sce) ? sce->world : NULL;
- bNodeTree *ntree= (sce) ? sce->nodetree : NULL;
+ bAnimContext ac = {NULL};
+ ListBase anim_data = {NULL, NULL};
+ bAnimListElem *ale;
+ int filter;
+ int ret=0;
+
+ bAnimListElem dummychan = {0};
- /* sanity check */
if (sce == NULL)
return 0;
- /* Scene's own animation */
- if (sce->adt) {
- if (adt_keyframes_loop(ked, sce->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
+ /* create a dummy wrapper data to work with */
+ dummychan.type = ANIMTYPE_SCENE;
+ dummychan.data = sce;
+ dummychan.id = &sce->id;
+ dummychan.adt = sce->adt;
- /* World */
- if (wo && wo->adt) {
- if (adt_keyframes_loop(ked, wo->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
- }
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
- /* NodeTree */
- if (ntree && ntree->adt) {
- if (adt_keyframes_loop(ked, ntree->adt, key_ok, key_cb, fcu_cb, filterflag))
- return 1;
+ /* get F-Curves to take keyframes from */
+ filter= ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through each F-Curve, applying the operation as required, but stopping on the first one */
+ for (ale= anim_data.first; ale; ale= ale->next) {
+ if (ANIM_fcurve_keyframes_loop(ked, (FCurve*)ale->data, key_ok, key_cb, fcu_cb)) {
+ ret = 1;
+ break;
+ }
}
+ BLI_freelistN(&anim_data);
- return 0;
+ /* return return code - defaults to zero if nothing happened */
+ return ret;
}
/* This function is used to loop over the keyframe data in a DopeSheet summary */
-static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int UNUSED(filterflag))
+static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -392,7 +296,7 @@ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, Key
return 0;
/* get F-Curves to take keyframes from */
- filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CURVESONLY);
+ filter= ANIMFILTER_DATA_VISIBLE;
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop through each F-Curve, working on the keyframes until the first curve aborts */
@@ -411,7 +315,7 @@ static short summary_keyframes_loop(KeyframeEditData *ked, bAnimContext *ac, Key
/* --- */
/* This function is used to apply operation to all keyframes, regardless of the type */
-short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag)
+short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, bAnimListElem *ale, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
/* sanity checks */
if (ale == NULL)
@@ -432,18 +336,18 @@ short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked, bAnimListElem *ale,
return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb);
case ALE_OB: /* object */
- return ob_keyframes_loop(ked, (Object *)ale->key_data, key_ok, key_cb, fcu_cb, filterflag);
+ return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb);
case ALE_SCE: /* scene */
- return scene_keyframes_loop(ked, (Scene *)ale->data, key_ok, key_cb, fcu_cb, filterflag);
+ return scene_keyframes_loop(ked, ads, (Scene *)ale->data, key_ok, key_cb, fcu_cb);
case ALE_ALL: /* 'all' (DopeSheet summary) */
- return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb, filterflag);
+ return summary_keyframes_loop(ked, (bAnimContext *)ale->data, key_ok, key_cb, fcu_cb);
}
return 0;
}
/* This function is used to apply operation to all keyframes, regardless of the type without needed an AnimListElem wrapper */
-short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb, int filterflag)
+short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
{
/* sanity checks */
if (data == NULL)
@@ -464,11 +368,11 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, void *data, int
return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb);
case ALE_OB: /* object */
- return ob_keyframes_loop(ked, (Object *)data, key_ok, key_cb, fcu_cb, filterflag);
+ return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb);
case ALE_SCE: /* scene */
- return scene_keyframes_loop(ked, (Scene *)data, key_ok, key_cb, fcu_cb, filterflag);
+ return scene_keyframes_loop(ked, ads, (Scene *)data, key_ok, key_cb, fcu_cb);
case ALE_ALL: /* 'all' (DopeSheet summary) */
- return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb, filterflag);
+ return summary_keyframes_loop(ked, (bAnimContext *)data, key_ok, key_cb, fcu_cb);
}
return 0;
@@ -486,7 +390,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
int filter;
/* filter animation data */
- filter= ANIMFILTER_CURVESONLY;
+ filter= ANIMFILTER_DATA_VISIBLE;
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
/* loop over F-Curves that are likely to have been edited, and check them */
@@ -510,7 +414,7 @@ void ANIM_editkeyframes_refresh(bAnimContext *ac)
/* run the given check on the 3 handles
* - check should be a macro, which takes the handle index as its single arg, which it substitutes later
- * - requires that a var, of type short, is named 'ok', and has been initialised ot 0
+ * - requires that a var, of type short, is named 'ok', and has been initialized to 0
*/
#define KEYFRAME_OK_CHECKS(check) \
{ \
@@ -532,7 +436,7 @@ static short ok_bezier_frame(KeyframeEditData *ked, BezTriple *bezt)
short ok = 0;
/* frame is stored in f1 property (this float accuracy check may need to be dropped?) */
- #define KEY_CHECK_OK(_index) IS_EQ(bezt->vec[_index][0], ked->f1)
+ #define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][0], ked->f1)
KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
@@ -572,7 +476,7 @@ static short ok_bezier_value(KeyframeEditData *ked, BezTriple *bezt)
* - this float accuracy check may need to be dropped?
* - should value be stored in f2 instead so that we won't have conflicts when using f1 for frames too?
*/
- #define KEY_CHECK_OK(_index) IS_EQ(bezt->vec[_index][1], ked->f1)
+ #define KEY_CHECK_OK(_index) IS_EQF(bezt->vec[_index][1], ked->f1)
KEYFRAME_OK_CHECKS(KEY_CHECK_OK);
#undef KEY_CHECK_OK
@@ -692,7 +596,7 @@ void bezt_remap_times(KeyframeEditData *ked, BezTriple *bezt)
static short snap_bezier_nearest(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
{
if (bezt->f2 & SELECT)
- bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
+ bezt->vec[1][0]= (float)(floorf(bezt->vec[1][0]+0.5f));
return 0;
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index 92fce2a77e5..e2afda04d30 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -25,6 +25,11 @@
* ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/editors/animation/keyframes_general.c
+ * \ingroup edanimation
+ */
+
+
#include <stdlib.h>
#include <string.h>
#include <math.h>
@@ -48,6 +53,7 @@
#include "BKE_global.h"
#include "RNA_access.h"
+#include "RNA_enum_types.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
@@ -105,9 +111,9 @@ void delete_fcurve_keys(FCurve *fcu)
{
int i;
- if(fcu->bezt==NULL) /* ignore baked curves */
+ if (fcu->bezt==NULL) /* ignore baked curves */
return;
-
+
/* Delete selected BezTriples */
for (i=0; i < fcu->totvert; i++) {
if (fcu->bezt[i].f2 & SELECT) {
@@ -118,7 +124,7 @@ void delete_fcurve_keys(FCurve *fcu)
}
/* Free the array of BezTriples if there are not keyframes */
- if(fcu->totvert == 0)
+ if (fcu->totvert == 0)
clear_fcurve_keys(fcu);
}
@@ -273,28 +279,21 @@ void clean_fcurve(FCurve *fcu, float thresh)
/* temp struct used for smooth_fcurve */
typedef struct tSmooth_Bezt {
float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */
+ float y1, y2, y3; /* averaged before/new/after y-values */
} tSmooth_Bezt;
/* Use a weighted moving-means method to reduce intensity of fluctuations */
+// TODO: introduce scaling factor for weighting falloff
void smooth_fcurve (FCurve *fcu)
{
BezTriple *bezt;
int i, x, totSel = 0;
- /* first loop through - count how many verts are selected, and fix up handles
- * this is done for both modes
- */
+ /* first loop through - count how many verts are selected */
bezt= fcu->bezt;
for (i=0; i < fcu->totvert; i++, bezt++) {
- if (BEZSELECTED(bezt)) {
- /* line point's handles up with point's vertical position */
- bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
- if ((bezt->h1==HD_AUTO) || (bezt->h1==HD_VECT)) bezt->h1= HD_ALIGN;
- if ((bezt->h2==HD_AUTO) || (bezt->h2==HD_VECT)) bezt->h2= HD_ALIGN;
-
- /* add value to total */
+ if (BEZSELECTED(bezt))
totSel++;
- }
}
/* if any points were selected, allocate tSmooth_Bezt points to work on */
@@ -314,7 +313,7 @@ void smooth_fcurve (FCurve *fcu)
tsb->h3 = &bezt->vec[2][1];
/* advance to the next tsb to populate */
- if (x < totSel- 1)
+ if (x < totSel-1)
tsb++;
else
break;
@@ -322,16 +321,16 @@ void smooth_fcurve (FCurve *fcu)
}
/* calculate the new smoothed F-Curve's with weighted averages:
- * - this is done with two passes
+ * - this is done with two passes to avoid progressive corruption errors
* - uses 5 points for each operation (which stores in the relevant handles)
* - previous: w/a ratio = 3:5:2:1:1
* - next: w/a ratio = 1:1:2:5:3
*/
- /* round 1: calculate previous and next */
+ /* round 1: calculate smoothing deltas and new values */
tsb= tarray;
for (i=0; i < totSel; i++, tsb++) {
- /* don't touch end points (otherwise, curves slowly explode) */
+ /* don't touch end points (otherwise, curves slowly explode, as we don't have enough data there) */
if (ELEM(i, 0, (totSel-1)) == 0) {
const tSmooth_Bezt *tP1 = tsb - 1;
const tSmooth_Bezt *tP2 = (i-2 > 0) ? (tsb - 2) : (NULL);
@@ -344,21 +343,26 @@ void smooth_fcurve (FCurve *fcu)
const float n1 = *tN1->h2;
const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2);
- /* calculate previous and next */
- *tsb->h1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
- *tsb->h3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
+ /* calculate previous and next, then new position by averaging these */
+ tsb->y1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12;
+ tsb->y3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12;
+
+ tsb->y2 = (tsb->y1 + tsb->y3) / 2;
}
}
- /* round 2: calculate new values and reset handles */
+ /* round 2: apply new values */
tsb= tarray;
for (i=0; i < totSel; i++, tsb++) {
- /* calculate new position by averaging handles */
- *tsb->h2 = (*tsb->h1 + *tsb->h3) / 2;
-
- /* reset handles now */
- *tsb->h1 = *tsb->h2;
- *tsb->h3 = *tsb->h2;
+ /* don't touch end points, as their values were't touched above */
+ if (ELEM(i, 0, (totSel-1)) == 0) {
+ /* y2 takes the average of the 2 points */
+ *tsb->h2 = tsb->y2;
+
+ /* handles are weighted between their original values and the averaged values */
+ *tsb->h1 = ((*tsb->h1) * 0.7f) + (tsb->y1 * 0.3f);
+ *tsb->h3 = ((*tsb->h3) * 0.7f) + (tsb->y3 * 0.3f);
+ }
}
/* free memory required for tarray */
@@ -452,7 +456,7 @@ void sample_fcurve (FCurve *fcu)
*/
/* globals for copy/paste data (like for other copy/paste buffers) */
-ListBase animcopybuf = {NULL, NULL};
+static ListBase animcopybuf = {NULL, NULL};
static float animcopy_firstframe= 999999999.0f;
static float animcopy_lastframe= -999999999.0f;
static float animcopy_cfra= 0.0;
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 8dc813d940b..109da669ce6 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
+/** \file blender/editors/animation/keyframing.c
+ * \ingroup edanimation
+ */
+
#include <stdio.h>
#include <stddef.h>
@@ -50,6 +55,7 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
@@ -294,6 +300,7 @@ int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt, short flag)
int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag)
{
BezTriple beztr= {{{0}}};
+ unsigned int oldTot = fcu->totvert;
int a;
/* set all three points, for nicer start position
@@ -329,10 +336,16 @@ int insert_vert_fcurve (FCurve *fcu, float x, float y, short flag)
if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE)==0) {
BezTriple *bezt= (fcu->bezt + a);
- /* set interpolation from previous (if available) */
- // FIXME: this doesn't work if user tweaked the interpolation specifically, and they were just overwriting some existing key in the process...
- if (a > 0) bezt->ipo= (bezt-1)->ipo;
- else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo;
+ /* set interpolation from previous (if available), but only if we didn't just replace some keyframe
+ * - replacement is indicated by no-change in number of verts
+ * - when replacing, the user may have specified some interpolation that should be kept
+ */
+ if (fcu->totvert > oldTot) {
+ if (a > 0)
+ bezt->ipo= (bezt-1)->ipo;
+ else if (a < fcu->totvert-1)
+ bezt->ipo= (bezt+1)->ipo;
+ }
/* don't recalculate handles if fast is set
* - this is a hack to make importers faster
@@ -353,7 +366,7 @@ enum {
KEYNEEDED_JUSTADD,
KEYNEEDED_DELPREV,
KEYNEEDED_DELNEXT
-} eKeyNeededStatus;
+} /*eKeyNeededStatus*/;
/* This helper function determines whether a new keyframe is needed */
/* Cases where keyframes should not be added:
@@ -390,14 +403,14 @@ static short new_key_needed (FCurve *fcu, float cFrame, float nValue)
prevVal= prev->vec[1][1];
/* keyframe to be added at point where there are already two similar points? */
- if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) {
+ if (IS_EQF(prevPosi, cFrame) && IS_EQF(beztPosi, cFrame) && IS_EQF(beztPosi, prevPosi)) {
return KEYNEEDED_DONTADD;
}
/* keyframe between prev+current points ? */
if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) {
/* is the value of keyframe to be added the same as keyframes on either side ? */
- if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) {
+ if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal)) {
return KEYNEEDED_DONTADD;
}
else {
@@ -407,7 +420,7 @@ static short new_key_needed (FCurve *fcu, float cFrame, float nValue)
realVal= evaluate_fcurve(fcu, cFrame);
/* compare whether it's the same as proposed */
- if (IS_EQ(realVal, nValue))
+ if (IS_EQF(realVal, nValue))
return KEYNEEDED_DONTADD;
else
return KEYNEEDED_JUSTADD;
@@ -420,7 +433,7 @@ static short new_key_needed (FCurve *fcu, float cFrame, float nValue)
* stays around or not depends on whether the values of previous/current
* beztriples and new keyframe are the same.
*/
- if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal))
+ if (IS_EQF(prevVal, nValue) && IS_EQF(beztVal, nValue) && IS_EQF(prevVal, beztVal))
return KEYNEEDED_DELNEXT;
else
return KEYNEEDED_JUSTADD;
@@ -458,7 +471,7 @@ static short new_key_needed (FCurve *fcu, float cFrame, float nValue)
else
valB= bezt->vec[1][1] + 1.0f;
- if (IS_EQ(valA, nValue) && IS_EQ(valA, valB))
+ if (IS_EQF(valA, nValue) && IS_EQF(valA, valB))
return KEYNEEDED_DELPREV;
else
return KEYNEEDED_JUSTADD;
@@ -648,41 +661,72 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_
mat4_to_eulO(eul, ob->rotmode, ob->obmat);
return eul[array_index];
}
+ else if (strstr(identifier, "rotation_quaternion")) {
+ float trimat[3][3], quat[4];
+
+ copy_m3_m4(trimat, ob->obmat);
+ mat3_to_quat_is_ok(quat, trimat);
+
+ return quat[array_index];
+ }
+ else if (strstr(identifier, "rotation_axis_angle")) {
+ float axis[3], angle;
+
+ mat4_to_axis_angle(axis, &angle, ob->obmat);
+
+ /* w = 0, x,y,z = 1,2,3 */
+ if (array_index == 0)
+ return angle;
+ else
+ return axis[array_index - 1];
+ }
}
}
else if (ptr->type == &RNA_PoseBone) {
- Object *ob= (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
+ Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */
bPoseChannel *pchan= (bPoseChannel *)ptr->data;
- bPoseChannel tchan;
+ float tmat[4][4];
- /* make a copy of pchan so that we can apply and decompose its chan_mat, thus getting the
- * rest-pose to pose-mode transform that got stored there at the end of posing calculations
- * for B-Bone deforms to use
- * - it should be safe to just make a local copy like this, since we're not doing anything with the copied pointers
+ /* Although it is not strictly required for this particular space conversion,
+ * arg1 must not be null, as there is a null check for the other conversions to
+ * be safe. Therefore, the active object is passed here, and in many cases, this
+ * will be what owns the pose-channel that is getting this anyway.
*/
- memcpy(&tchan, pchan, sizeof(bPoseChannel));
- pchan_apply_mat4(&tchan, pchan->chan_mat);
+ copy_m4_m4(tmat, pchan->pose_mat);
+ constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
/* Loc, Rot/Quat keyframes are supported... */
if (strstr(identifier, "location")) {
/* only use for non-connected bones */
if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED))
- return tchan.loc[array_index];
+ return tmat[3][array_index];
else if (pchan->bone->parent == NULL)
- return tchan.loc[array_index];
+ return tmat[3][array_index];
}
else if (strstr(identifier, "rotation_euler")) {
- return tchan.eul[array_index];
+ float eul[3];
+
+ mat4_to_eulO(eul, pchan->rotmode, tmat);
+ return eul[array_index];
}
else if (strstr(identifier, "rotation_quaternion")) {
- return tchan.quat[array_index];
+ float trimat[3][3], quat[4];
+
+ copy_m3_m4(trimat, tmat);
+ mat3_to_quat_is_ok(quat, trimat);
+
+ return quat[array_index];
}
- else if (strstr(identifier, "rotation_axisangle")) {
+ else if (strstr(identifier, "rotation_axis_angle")) {
+ float axis[3], angle;
+
+ mat4_to_axis_angle(axis, &angle, tmat);
+
/* w = 0, x,y,z = 1,2,3 */
if (array_index == 0)
- return tchan.rotAngle;
+ return angle;
else
- return tchan.rotAxis[array_index - 1];
+ return axis[array_index - 1];
}
}
@@ -903,7 +947,7 @@ short insert_keyframe (ReportList *reports, ID *id, bAction *act, const char gro
/* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor,
* is determined by the array index for the F-Curve
*/
- if (ELEM4(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR)) {
+ if (ELEM5(RNA_property_subtype(prop), PROP_TRANSLATION, PROP_XYZ, PROP_EULER, PROP_COLOR, PROP_COORDS)) {
fcu->color_mode= FCURVE_COLOR_AUTO_RGB;
}
}
@@ -1036,7 +1080,7 @@ short delete_keyframe (ReportList *reports, ID *id, bAction *act, const char gro
enum {
COMMONKEY_MODE_INSERT = 0,
COMMONKEY_MODE_DELETE,
-} eCommonModifyKey_Modes;
+} /*eCommonModifyKey_Modes*/;
/* Polling callback for use with ANIM_*_keyframe() operators
* This is based on the standard ED_operator_areaactive callback,
@@ -1274,7 +1318,7 @@ void ANIM_OT_keyframe_delete (wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name= "Delete Keyframe";
+ ot->name= "Delete Keying-Set Keyframe";
ot->idname= "ANIM_OT_keyframe_delete";
ot->description= "Delete keyframes on the current frame for all properties in the specified Keying Set";
@@ -1319,7 +1363,7 @@ static int delete_key_v3d_exec (bContext *C, wmOperator *op)
short success= 0;
/* loop through all curves in animdata and delete keys on this frame */
- if (ob->adt) {
+ if ((ob->adt) && (ob->adt->action)) {
AnimData *adt= ob->adt;
bAction *act= adt->action;
@@ -1329,7 +1373,7 @@ static int delete_key_v3d_exec (bContext *C, wmOperator *op)
}
}
- BKE_reportf(op->reports, RPT_INFO, "Ob '%s' - Successfully removed %d keyframes \n", id->name+2, success);
+ BKE_reportf(op->reports, RPT_INFO, "Ob '%s' - Successfully had %d keyframes removed", id->name+2, success);
ob->recalc |= OB_RECALC_OB;
}
@@ -1347,6 +1391,7 @@ void ANIM_OT_keyframe_delete_v3d (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Delete Keyframe";
+ ot->description= "Remove keyframes on current frame for selected object";
ot->idname= "ANIM_OT_keyframe_delete_v3d";
/* callbacks */
@@ -1366,7 +1411,7 @@ static int insert_key_button_exec (bContext *C, wmOperator *op)
{
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
PropertyRNA *prop= NULL;
char *path;
float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
@@ -1455,7 +1500,7 @@ static int delete_key_button_exec (bContext *C, wmOperator *op)
{
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
PropertyRNA *prop= NULL;
char *path;
float cfra= (float)CFRA; // XXX for now, don't bother about all the yucky offset crap
@@ -1577,7 +1622,7 @@ short fcurve_frame_has_keyframe (FCurve *fcu, float frame, short filter)
/* Checks whether an Action has a keyframe for a given frame
* Since we're only concerned whether a keyframe exists, we can simply loop until a match is found...
*/
-short action_frame_has_keyframe (bAction *act, float frame, short filter)
+static short action_frame_has_keyframe (bAction *act, float frame, short filter)
{
FCurve *fcu;
@@ -1605,7 +1650,7 @@ short action_frame_has_keyframe (bAction *act, float frame, short filter)
}
/* Checks whether an Object has a keyframe for a given frame */
-short object_frame_has_keyframe (Object *ob, float frame, short filter)
+static short object_frame_has_keyframe (Object *ob, float frame, short filter)
{
/* error checking */
if (ob == NULL)
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index 2df7d21e907..69e7c4eb73a 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -1,4 +1,4 @@
-/**
+/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
@@ -26,6 +26,11 @@
*
* ***** END GPL LICENSE BLOCK *****
*/
+
+/** \file blender/editors/animation/keyingsets.c
+ * \ingroup edanimation
+ */
+
#include <stdio.h>
#include <stddef.h>
@@ -54,6 +59,7 @@
#include "ED_screen.h"
#include "UI_interface.h"
+#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -218,6 +224,7 @@ static int add_empty_ks_path_exec (bContext *C, wmOperator *op)
ksp->groupmode= KSP_GROUP_KSNAME; // XXX?
ksp->idtype= ID_OB;
+ ksp->flag= KSP_FLAG_WHOLE_ARRAY;
return OPERATOR_FINISHED;
}
@@ -288,7 +295,7 @@ static int add_keyingset_button_exec (bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
KeyingSet *ks = NULL;
PropertyRNA *prop= NULL;
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
char *path = NULL;
short success= 0;
int index=0, pflag=0;
@@ -388,7 +395,7 @@ static int remove_keyingset_button_exec (bContext *C, wmOperator *op)
Scene *scene= CTX_data_scene(C);
KeyingSet *ks = NULL;
PropertyRNA *prop= NULL;
- PointerRNA ptr= {{0}};
+ PointerRNA ptr= {{NULL}};
char *path = NULL;
short success= 0;
int index=0;
@@ -509,7 +516,7 @@ void ANIM_OT_keying_set_active_set (wmOperatorType *ot)
/* REGISTERED KEYING SETS */
/* Keying Set Type Info declarations */
-ListBase keyingset_type_infos = {NULL, NULL};
+static ListBase keyingset_type_infos = {NULL, NULL};
/* Built-In Keying Sets (referencing type infos)*/
ListBase builtin_keyingsets = {NULL, NULL};
@@ -572,9 +579,8 @@ void ANIM_keyingset_info_register (KeyingSetInfo *ksi)
}
/* Remove the given KeyingSetInfo from the list of type infos, and also remove the builtin set if appropriate */
-void ANIM_keyingset_info_unregister (const bContext *C, KeyingSetInfo *ksi)
+void ANIM_keyingset_info_unregister (Main *bmain, KeyingSetInfo *ksi)
{
- Main *bmain= CTX_data_main(C);
KeyingSet *ks, *ksn;
/* find relevant builtin KeyingSets which use this, and remove them */
@@ -691,7 +697,7 @@ KeyingSet *ANIM_get_keyingset_for_autokeying(Scene *scene, const char *tranformK
/* Menu of All Keying Sets ----------------------------- */
/* Dynamically populate an enum of Keying Sets */
-EnumPropertyItem *ANIM_keying_sets_enum_itemf (bContext *C, PointerRNA *UNUSED(ptr), int *free)
+EnumPropertyItem *ANIM_keying_sets_enum_itemf (bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
Scene *scene = CTX_data_scene(C);
KeyingSet *ks;
@@ -760,14 +766,14 @@ void ANIM_keying_sets_menu_setup (bContext *C, const char title[], const char op
uiLayout *layout;
int i = 0;
- pup= uiPupMenuBegin(C, title, ICON_NULL);
+ pup= uiPupMenuBegin(C, title, ICON_NONE);
layout= uiPupMenuLayout(pup);
/* active Keying Set
* - only include entry if it exists
*/
if (scene->active_keyingset) {
- uiItemIntO(layout, "Active Keying Set", ICON_NULL, op_name, "type", i++);
+ uiItemIntO(layout, "Active Keying Set", ICON_NONE, op_name, "type", i++);
uiItemS(layout);
}
else
@@ -777,19 +783,19 @@ void ANIM_keying_sets_menu_setup (bContext *C, const char title[], const char op
* - these are listed in the order in which they were defined for the active scene
*/
if (scene->keyingsets.first) {
- for (ks= scene->keyingsets.first; ks; ks= ks->next) {
+ for (ks= scene->keyingsets.first; ks; ks=ks->next, i++) {
if (ANIM_keyingset_context_ok_poll(C, ks))
- uiItemIntO(layout, ks->name, ICON_NULL, op_name, "type", i++);
+ uiItemIntO(layout, ks->name, ICON_NONE, op_name, "type", i);
}
uiItemS(layout);
}
/* builtin Keying Sets */
i= -1;
- for (ks= builtin_keyingsets.first; ks; ks= ks->next) {
+ for (ks= builtin_keyingsets.first; ks; ks=ks->next, i--) {
/* only show KeyingSet if context is suitable */
if (ANIM_keyingset_context_ok_poll(C, ks))
- uiItemIntO(layout, ks->name, ICON_NULL, op_name, "type", i--);
+ uiItemEnumO_value(layout, ks->name, ICON_NONE, op_name, "type", i);
}
uiPupMenuEnd(C, pup);
@@ -937,6 +943,14 @@ int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingS
int arraylen, i;
short kflag2;
+ /* skip path if no ID pointer is specified */
+ if (ksp->id == NULL) {
+ BKE_reportf(reports, RPT_WARNING,
+ "Skipping path in Keying Set, as it has no ID (KS = '%s', Path = '%s'[%d])",
+ ks->name, ksp->rna_path, ksp->array_index);
+ continue;
+ }
+
/* since keying settings can be defined on the paths too, extend the path before using it */
kflag2 = (kflag | ksp->keyingflag);
@@ -980,20 +994,18 @@ int ANIM_apply_keyingset (bContext *C, ListBase *dsources, bAction *act, KeyingS
}
/* set recalc-flags */
- if (ksp->id) {
- switch (GS(ksp->id->name)) {
- case ID_OB: /* Object (or Object-Related) Keyframes */
- {
- Object *ob= (Object *)ksp->id;
-
- ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: only object transforms only?
- }
- break;
+ switch (GS(ksp->id->name)) {
+ case ID_OB: /* Object (or Object-Related) Keyframes */
+ {
+ Object *ob= (Object *)ksp->id;
+
+ ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; // XXX: only object transforms only?
}
-
- /* send notifiers for updates (this doesn't require context to work!) */
- WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+ break;
}
+
+ /* send notifiers for updates (this doesn't require context to work!) */
+ WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
}
/* return the number of channels successfully affected */