WIP: Anim: Baklava, add Animation data-block to anim filtering code #119875
|
@ -123,6 +123,13 @@ void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu)
|
|||
*/
|
||||
animdata_remove_empty_action(adt);
|
||||
}
|
||||
else if (adt->animation) {
|
||||
/* TODO: support deleting FCurves from Animation data-blocks. */
|
||||
return;
|
||||
}
|
||||
else {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
BKE_fcurve_free(fcu);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ endif()
|
|||
|
||||
if(WITH_EXPERIMENTAL_FEATURES)
|
||||
add_definitions(-DWITH_GREASE_PENCIL_V3)
|
||||
add_definitions(-DWITH_ANIM_BAKLAVA)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <cstdio>
|
||||
|
||||
#include "ANIM_action.hh"
|
||||
#include "ANIM_animation.hh"
|
||||
#include "ANIM_animdata.hh"
|
||||
#include "ANIM_keyframing.hh"
|
||||
|
||||
|
@ -76,6 +77,8 @@
|
|||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
/* *********************************************** */
|
||||
/* XXX constant defines to be moved elsewhere? */
|
||||
|
||||
|
@ -1246,6 +1249,94 @@ static bAnimChannelType ACF_NLACURVE = {
|
|||
/*setting_ptr*/ acf_fcurve_setting_ptr,
|
||||
};
|
||||
|
||||
/* Object Animation Expander ------------------------------------------- */
|
||||
|
||||
#ifdef WITH_ANIM_BAKLAVA
|
||||
|
||||
/* TODO: just get this from RNA? */
|
||||
static int acf_fillanim_icon(bAnimListElem * /*ale*/)
|
||||
{
|
||||
return ICON_ACTION; /* TODO: give Animation its own icon? */
|
||||
}
|
||||
|
||||
/* check if some setting exists for this channel */
|
||||
static bool acf_fillanim_setting_valid(bAnimContext * /*ac*/,
|
||||
bAnimListElem * /*ale*/,
|
||||
eAnimChannel_Settings setting)
|
||||
{
|
||||
switch (setting) {
|
||||
case ACHANNEL_SETTING_SELECT:
|
||||
case ACHANNEL_SETTING_EXPAND:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the appropriate flag(s) for the setting when it is valid. */
|
||||
static int acf_fillanim_setting_flag(bAnimContext * /*ac*/,
|
||||
eAnimChannel_Settings setting,
|
||||
bool *r_neg)
|
||||
{
|
||||
*r_neg = false;
|
||||
|
||||
switch (setting) {
|
||||
case ACHANNEL_SETTING_SELECT:
|
||||
return ADT_UI_SELECTED;
|
||||
|
||||
case ACHANNEL_SETTING_EXPAND:
|
||||
return ADT_UI_EXPANDED;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* get pointer to the setting */
|
||||
static void *acf_fillanim_setting_ptr(bAnimListElem *ale,
|
||||
eAnimChannel_Settings setting,
|
||||
short *r_type)
|
||||
{
|
||||
AnimData *adt = ale->adt;
|
||||
BLI_assert(adt);
|
||||
|
||||
*r_type = 0;
|
||||
|
||||
switch (setting) {
|
||||
case ACHANNEL_SETTING_SELECT:
|
||||
return GET_ACF_FLAG_PTR(adt->flag, r_type);
|
||||
|
||||
case ACHANNEL_SETTING_EXPAND:
|
||||
return GET_ACF_FLAG_PTR(adt->flag, r_type);
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/** Object Animation expander type define. */
|
||||
static bAnimChannelType ACF_FILLANIM = {
|
||||
/*channel_type_name*/ "Ob-Animation Filler",
|
||||
/*channel_role*/ ACHANNEL_ROLE_EXPANDER,
|
||||
|
||||
/*get_backdrop_color*/ acf_generic_dataexpand_color,
|
||||
/*get_channel_color*/ nullptr,
|
||||
/*draw_backdrop*/ acf_generic_dataexpand_backdrop,
|
||||
/*get_indent_level*/ acf_generic_indentation_1,
|
||||
/*get_offset*/ acf_generic_basic_offset,
|
||||
|
||||
/*name*/ acf_generic_idblock_name,
|
||||
/*name_prop*/ acf_generic_idfill_name_prop,
|
||||
/*icon*/ acf_fillanim_icon,
|
||||
|
||||
/*has_setting*/ acf_fillanim_setting_valid,
|
||||
/*setting_flag*/ acf_fillanim_setting_flag,
|
||||
/*setting_ptr*/ acf_fillanim_setting_ptr,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Object Action Expander ------------------------------------------- */
|
||||
|
||||
/* TODO: just get this from RNA? */
|
||||
|
@ -4280,6 +4371,11 @@ static void ANIM_init_channel_typeinfo_data()
|
|||
animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
|
||||
animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */
|
||||
|
||||
#ifdef WITH_ANIM_BAKLAVA
|
||||
animchannelTypeInfo[type++] = &ACF_FILLANIM; /* Object Animation Expander */
|
||||
#else
|
||||
animchannelTypeInfo[type++] = nullptr;
|
||||
#endif
|
||||
animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
|
||||
animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
|
||||
|
||||
|
@ -4325,6 +4421,11 @@ static void ANIM_init_channel_typeinfo_data()
|
|||
|
||||
animchannelTypeInfo[type++] = &ACF_NLATRACK; /* NLA Track */
|
||||
animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
|
||||
|
||||
#ifdef WITH_ANIM_BAKLAVA
|
||||
BLI_assert_msg(animchannelTypeInfo[ANIMTYPE_FILLANIM] == &ACF_FILLANIM,
|
||||
"ANIMTYPE_FILLANIM does not match ACF_FILLANIM");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -256,6 +256,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
|
|||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_FILLANIM: /* Animation Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
|
@ -312,6 +313,7 @@ void ANIM_set_active_channel(bAnimContext *ac,
|
|||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_FILLANIM: /* Animation Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
|
@ -365,6 +367,7 @@ bool ANIM_is_active_channel(bAnimListElem *ale)
|
|||
{
|
||||
switch (ale->type) {
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_FILLANIM: /* Animation Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
|
@ -501,6 +504,7 @@ static eAnimChannels_SetFlag anim_channels_selection_flag_for_toggle(const ListB
|
|||
break;
|
||||
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_FILLANIM: /* Animation Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
|
@ -615,6 +619,7 @@ static void anim_channels_select_set(bAnimContext *ac,
|
|||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_FILLANIM: /* Animation Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
|
@ -3832,6 +3837,7 @@ static int mouse_anim_channels(bContext *C,
|
|||
notifierFlags |= click_select_channel_object(C, ac, ale, selectmode);
|
||||
break;
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_FILLANIM: /* Animation Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
|
|
|
@ -55,7 +55,10 @@ void ANIM_list_elem_update(Main *bmain, Scene *scene, bAnimListElem *ale)
|
|||
adt = BKE_animdata_from_id(id);
|
||||
if (adt) {
|
||||
DEG_id_tag_update(id, ID_RECALC_ANIMATION);
|
||||
if (adt->action != nullptr) {
|
||||
if (adt->animation != nullptr) {
|
||||
DEG_id_tag_update(&adt->animation->id, ID_RECALC_ANIMATION);
|
||||
}
|
||||
else if (adt->action != nullptr) {
|
||||
DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,8 +88,11 @@
|
|||
#include "SEQ_sequencer.hh"
|
||||
#include "SEQ_utils.hh"
|
||||
|
||||
#include "ANIM_animation.hh"
|
||||
#include "ANIM_bone_collections.hh"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
/* ************************************************************ */
|
||||
/* Blender Context <-> Animation Context mapping */
|
||||
|
||||
|
@ -446,14 +449,14 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
|
|||
|
||||
/* ............................... */
|
||||
|
||||
/* quick macro to test if AnimData is usable */
|
||||
#define ANIMDATA_HAS_KEYS(id) ((id)->adt && (id)->adt->action)
|
||||
/* quick macro to test if AnimData has usable Action */
|
||||
#define ANIMDATA_HAS_KEYS(id) ((id)->adt && !(id)->adt->animation && (id)->adt->action)
|
||||
|
||||
/* quick macro to test if AnimData is usable for drivers */
|
||||
#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)
|
||||
|
||||
/* quick macro to test if AnimData is usable for NLA */
|
||||
#define ANIMDATA_HAS_NLA(id) ((id)->adt && (id)->adt->nla_tracks.first)
|
||||
#define ANIMDATA_HAS_NLA(id) ((id)->adt && !(id)->adt->animation && (id)->adt->nla_tracks.first)
|
||||
|
||||
/**
|
||||
* Quick macro to test for all three above usability tests, performing the appropriate provided
|
||||
|
@ -478,6 +481,7 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
|
|||
* - driversOk: line or block of code to execute for Drivers case
|
||||
* - nlaKeysOk: line or block of code for NLA Strip Keyframes case
|
||||
* - keysOk: line or block of code for Keyframes case
|
||||
* - animOk: line or block of code for Keyframes from Animation data blocks case
|
||||
*
|
||||
* The checks for the various cases are as follows:
|
||||
* 0) top level: checks for animdata and also that all the F-Curves for the block will be visible
|
||||
|
@ -489,8 +493,9 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
|
|||
* 3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
|
||||
* 4A) nla strip keyframes: these are the per-strip controls for time and influence
|
||||
* 4B) normal keyframes: only when there is an active action
|
||||
* 4C) normal keyframes: only when there is an Animation assigned
|
||||
*/
|
||||
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk) \
|
||||
#define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, nlaKeysOk, keysOk, animOk) \
|
||||
{ \
|
||||
if ((id)->adt) { \
|
||||
if (!(filter_mode & ANIMFILTER_CURVE_VISIBLE) || \
|
||||
|
@ -511,6 +516,9 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
|
|||
driversOk \
|
||||
} \
|
||||
} \
|
||||
else if ((id)->adt->animation) { \
|
||||
animOk \
|
||||
} \
|
||||
else { \
|
||||
if (ANIMDATA_HAS_NLA(id)) { \
|
||||
nlaKeysOk \
|
||||
|
@ -580,6 +588,36 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
|
|||
|
||||
/* ----------- 'Private' Stuff --------------- */
|
||||
|
||||
/**
|
||||
* Set `ale` so that it points to the top-most 'summary' channel of the given `adt`.
|
||||
* So this is either the Animation or the Action, or empty.
|
||||
*/
|
||||
static void key_data_from_adt(bAnimListElem &ale, AnimData *adt)
|
||||
{
|
||||
ale.adt = adt;
|
||||
|
||||
if (!adt) {
|
||||
ale.key_data = nullptr;
|
||||
ale.datatype = ALE_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (adt->animation) {
|
||||
ale.key_data = adt->animation;
|
||||
ale.datatype = ALE_ANIM;
|
||||
return;
|
||||
}
|
||||
|
||||
if (adt->action) {
|
||||
ale.key_data = adt->action;
|
||||
ale.datatype = ALE_ACT;
|
||||
return;
|
||||
}
|
||||
|
||||
ale.key_data = nullptr;
|
||||
ale.datatype = ALE_NONE;
|
||||
}
|
||||
|
||||
/* this function allocates memory for a new bAnimListElem struct for the
|
||||
* provided animation channel-data.
|
||||
*/
|
||||
|
@ -634,6 +672,15 @@ static bAnimListElem *make_new_animlistelem(void *data,
|
|||
ale->adt = BKE_animdata_from_id(&ob->id);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLANIM: {
|
||||
Animation *anim = (Animation *)data;
|
||||
|
||||
ale->flag = anim->flag;
|
||||
|
||||
ale->key_data = anim;
|
||||
ale->datatype = ALE_ANIM;
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLACTD: {
|
||||
bAction *act = (bAction *)data;
|
||||
|
||||
|
@ -655,244 +702,125 @@ static bAnimListElem *make_new_animlistelem(void *data,
|
|||
}
|
||||
case ANIMTYPE_DSMAT: {
|
||||
Material *ma = (Material *)data;
|
||||
AnimData *adt = ma->adt;
|
||||
|
||||
ale->flag = FILTER_MAT_OBJD(ma);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, ma->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSLAM: {
|
||||
Light *la = (Light *)data;
|
||||
AnimData *adt = la->adt;
|
||||
|
||||
ale->flag = FILTER_LAM_OBJD(la);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, la->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSCAM: {
|
||||
Camera *ca = (Camera *)data;
|
||||
AnimData *adt = ca->adt;
|
||||
|
||||
ale->flag = FILTER_CAM_OBJD(ca);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, ca->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSCACHEFILE: {
|
||||
CacheFile *cache_file = (CacheFile *)data;
|
||||
AnimData *adt = cache_file->adt;
|
||||
|
||||
ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, cache_file->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSCUR: {
|
||||
Curve *cu = (Curve *)data;
|
||||
AnimData *adt = cu->adt;
|
||||
|
||||
ale->flag = FILTER_CUR_OBJD(cu);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, cu->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSARM: {
|
||||
bArmature *arm = (bArmature *)data;
|
||||
AnimData *adt = arm->adt;
|
||||
|
||||
ale->flag = FILTER_ARM_OBJD(arm);
|
||||
dr.sybren marked this conversation as resolved
Outdated
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, arm->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSMESH: {
|
||||
Mesh *mesh = (Mesh *)data;
|
||||
AnimData *adt = mesh->adt;
|
||||
|
||||
ale->flag = FILTER_MESH_OBJD(mesh);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, mesh->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSLAT: {
|
||||
Lattice *lt = (Lattice *)data;
|
||||
AnimData *adt = lt->adt;
|
||||
|
||||
ale->flag = FILTER_LATTICE_OBJD(lt);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, lt->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSSPK: {
|
||||
Speaker *spk = (Speaker *)data;
|
||||
AnimData *adt = spk->adt;
|
||||
|
||||
ale->flag = FILTER_SPK_OBJD(spk);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, spk->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSHAIR: {
|
||||
Curves *curves = (Curves *)data;
|
||||
AnimData *adt = curves->adt;
|
||||
|
||||
ale->flag = FILTER_CURVES_OBJD(curves);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, curves->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSPOINTCLOUD: {
|
||||
PointCloud *pointcloud = (PointCloud *)data;
|
||||
AnimData *adt = pointcloud->adt;
|
||||
|
||||
ale->flag = FILTER_POINTS_OBJD(pointcloud);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, pointcloud->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSVOLUME: {
|
||||
Volume *volume = (Volume *)data;
|
||||
AnimData *adt = volume->adt;
|
||||
|
||||
ale->flag = FILTER_VOLUME_OBJD(volume);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, volume->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSSKEY: {
|
||||
Key *key = (Key *)data;
|
||||
AnimData *adt = key->adt;
|
||||
|
||||
ale->flag = FILTER_SKE_OBJD(key);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, key->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSWOR: {
|
||||
World *wo = (World *)data;
|
||||
AnimData *adt = wo->adt;
|
||||
|
||||
ale->flag = FILTER_WOR_SCED(wo);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, wo->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSNTREE: {
|
||||
bNodeTree *ntree = (bNodeTree *)data;
|
||||
AnimData *adt = ntree->adt;
|
||||
|
||||
ale->flag = FILTER_NTREE_DATA(ntree);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, ntree->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSLINESTYLE: {
|
||||
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)data;
|
||||
AnimData *adt = linestyle->adt;
|
||||
|
||||
ale->flag = FILTER_LS_SCED(linestyle);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, linestyle->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSPART: {
|
||||
ParticleSettings *part = (ParticleSettings *)ale->data;
|
||||
AnimData *adt = part->adt;
|
||||
|
||||
ale->flag = FILTER_PART_OBJD(part);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, part->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSTEX: {
|
||||
Tex *tex = (Tex *)data;
|
||||
AnimData *adt = tex->adt;
|
||||
|
||||
ale->flag = FILTER_TEX_DATA(tex);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, tex->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSGPENCIL: {
|
||||
bGPdata *gpd = (bGPdata *)data;
|
||||
AnimData *adt = gpd->adt;
|
||||
|
||||
/* NOTE: we just reuse the same expand filter for this case */
|
||||
ale->flag = EXPANDED_GPD(gpd);
|
||||
|
||||
/* XXX: currently, this is only used for access to its animation data */
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, gpd->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_DSMCLIP: {
|
||||
MovieClip *clip = (MovieClip *)data;
|
||||
AnimData *adt = clip->adt;
|
||||
|
||||
ale->flag = EXPANDED_MCLIP(clip);
|
||||
|
||||
ale->key_data = (adt) ? adt->action : nullptr;
|
||||
ale->datatype = ALE_ACT;
|
||||
|
||||
ale->adt = BKE_animdata_from_id(static_cast<ID *>(data));
|
||||
key_data_from_adt(*ale, clip->adt);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_NLACONTROLS: {
|
||||
|
@ -1366,6 +1294,37 @@ static size_t animfilter_fcurves(ListBase *anim_data,
|
|||
return items;
|
||||
}
|
||||
|
||||
static size_t animfilter_fcurves_span(ListBase * /*bAnimListElem*/ anim_data,
|
||||
bDopeSheet * /*ads*/,
|
||||
Span<FCurve *> fcurves,
|
||||
const int filter_mode,
|
||||
ID *owner_id,
|
||||
ID *fcurve_owner_id)
|
||||
{
|
||||
size_t num_items = 0;
|
||||
BLI_assert(owner_id);
|
||||
|
||||
for (FCurve *fcu : fcurves) {
|
||||
/* make_new_animlistelem will return nullptr when fcu == nullptr, and that's
|
||||
* going to cause problems. */
|
||||
BLI_assert(fcu);
|
||||
|
||||
/* TODO: deal with `filter_mode` and `ads->filterflag`.
|
||||
* See `animfilter_fcurve_next()`. */
|
||||
|
||||
if (filter_mode & ANIMFILTER_TMP_PEEK) {
|
||||
/* Found an animation channel, which is good enough for the 'TMP_PEEK' mode. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
bAnimListElem *ale = make_new_animlistelem(fcu, ANIMTYPE_FCURVE, owner_id, fcurve_owner_id);
|
||||
BLI_addtail(anim_data, ale);
|
||||
num_items++;
|
||||
}
|
||||
|
||||
return num_items;
|
||||
}
|
||||
|
||||
static size_t animfilter_act_group(bAnimContext *ac,
|
||||
ListBase *anim_data,
|
||||
bDopeSheet *ads,
|
||||
|
@ -1501,6 +1460,32 @@ static size_t animfilter_action(bAnimContext *ac,
|
|||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add animation list elements for FCurves in an Animation data-block.
|
||||
*/
|
||||
static size_t animfilter_animation_fcurves(
|
||||
ListBase *anim_data, bDopeSheet *ads, AnimData *adt, const int filter_mode, ID *owner_id)
|
||||
{
|
||||
/* If this ID is not bound, there is nothing to show. */
|
||||
if (adt->binding_handle == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLI_assert(adt->animation); /* Otherwise this function wouldn't be called. */
|
||||
animrig::Animation &anim = adt->animation->wrap();
|
||||
|
||||
/* Don't include anything from this animation if it is linked in from another
|
||||
* file, and we're getting stuff for editing... */
|
||||
if ((filter_mode & ANIMFILTER_FOREDIT) && (ID_IS_LINKED(&anim) || ID_IS_OVERRIDE_LIBRARY(&anim)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For now we don't show layers anywhere, just the contained F-Curves. */
|
||||
Span<FCurve *> fcurves = animrig::fcurves_for_animation(anim, adt->binding_handle);
|
||||
return animfilter_fcurves_span(anim_data, ads, fcurves, filter_mode, owner_id, &anim.id);
|
||||
}
|
||||
|
||||
/* Include NLA-Data for NLA-Editor:
|
||||
* - 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
|
||||
|
@ -1692,8 +1677,11 @@ static size_t animfilter_block_data(
|
|||
{ /* NLA Control Keyframes */
|
||||
items += animfilter_nla_controls(anim_data, ads, adt, filter_mode, id);
|
||||
},
|
||||
{ /* Keyframes */
|
||||
{ /* Keyframes from Action. */
|
||||
items += animfilter_action(ac, anim_data, ads, adt->action, filter_mode, id);
|
||||
},
|
||||
{ /* Keyframes from Animation. */
|
||||
items += animfilter_animation_fcurves(anim_data, ads, adt, filter_mode, id);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2968,10 +2956,15 @@ static size_t animdata_filter_ds_obanim(
|
|||
expanded = EXPANDED_DRVD(adt);
|
||||
},
|
||||
{/* NLA Strip Controls - no dedicated channel for now (XXX) */},
|
||||
{ /* Keyframes */
|
||||
{ /* Keyframes from Action. */
|
||||
type = ANIMTYPE_FILLACTD;
|
||||
cdata = adt->action;
|
||||
expanded = EXPANDED_ACTC(adt->action);
|
||||
},
|
||||
{ /* Keyframes from Animation. */
|
||||
type = ANIMTYPE_FILLANIM;
|
||||
cdata = adt->animation;
|
||||
expanded = EXPANDED_ADT(adt);
|
||||
});
|
||||
|
||||
/* add object-level animation channels */
|
||||
|
@ -3147,10 +3140,15 @@ static size_t animdata_filter_ds_scene(
|
|||
expanded = EXPANDED_DRVD(adt);
|
||||
},
|
||||
{/* NLA Strip Controls - no dedicated channel for now (XXX) */},
|
||||
{ /* Keyframes */
|
||||
{ /* Keyframes from Action. */
|
||||
type = ANIMTYPE_FILLACTD;
|
||||
cdata = adt->action;
|
||||
expanded = EXPANDED_ACTC(adt->action);
|
||||
},
|
||||
{ /* Keyframes from Animation. */
|
||||
type = ANIMTYPE_FILLANIM;
|
||||
cdata = adt->animation;
|
||||
expanded = EXPANDED_ADT(adt);
|
||||
});
|
||||
|
||||
/* add scene-level animation channels */
|
||||
|
|
|
@ -376,6 +376,7 @@ enum class ChannelType {
|
|||
SCENE,
|
||||
OBJECT,
|
||||
FCURVE,
|
||||
ANIMATION,
|
||||
ACTION,
|
||||
ACTION_GROUP,
|
||||
GREASE_PENCIL_CELS,
|
||||
|
@ -401,6 +402,7 @@ struct ChannelListElement {
|
|||
Object *ob;
|
||||
AnimData *adt;
|
||||
FCurve *fcu;
|
||||
Animation *anim;
|
||||
bAction *act;
|
||||
bActionGroup *agrp;
|
||||
bGPDlayer *gpl;
|
||||
|
@ -429,6 +431,10 @@ static void build_channel_keylist(ChannelListElement *elem, blender::float2 rang
|
|||
fcurve_to_keylist(elem->adt, elem->fcu, elem->keylist, elem->saction_flag, range);
|
||||
break;
|
||||
}
|
||||
case ChannelType::ANIMATION: {
|
||||
animation_to_keylist(elem->adt, elem->anim, elem->keylist, elem->saction_flag, range);
|
||||
break;
|
||||
}
|
||||
case ChannelType::ACTION: {
|
||||
action_to_keylist(elem->adt, elem->act, elem->keylist, elem->saction_flag, range);
|
||||
break;
|
||||
|
@ -697,6 +703,25 @@ void ED_add_action_group_channel(ChannelDrawList *channel_list,
|
|||
draw_elem->channel_locked = locked;
|
||||
}
|
||||
|
||||
void ED_add_animation_channel(ChannelDrawList *channel_list,
|
||||
AnimData *adt,
|
||||
Animation *anim,
|
||||
const float ypos,
|
||||
const float yscale_fac,
|
||||
int saction_flag)
|
||||
{
|
||||
BLI_assert(anim);
|
||||
|
||||
const bool locked = (anim && (ID_IS_LINKED(anim) || ID_IS_OVERRIDE_LIBRARY(anim)));
|
||||
saction_flag &= ~SACTION_SHOW_EXTREMES;
|
||||
|
||||
ChannelListElement *draw_elem = channel_list_add_element(
|
||||
channel_list, ChannelType::ANIMATION, ypos, yscale_fac, eSAction_Flag(saction_flag));
|
||||
draw_elem->adt = adt;
|
||||
draw_elem->anim = anim;
|
||||
draw_elem->channel_locked = locked;
|
||||
}
|
||||
|
||||
void ED_add_action_channel(ChannelDrawList *channel_list,
|
||||
AnimData *adt,
|
||||
bAction *act,
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#include "ED_keyframes_edit.hh"
|
||||
#include "ED_markers.hh"
|
||||
|
||||
#include "ANIM_animation.hh"
|
||||
|
||||
using namespace blender;
|
||||
|
||||
/* This file defines an API and set of callback-operators for
|
||||
* non-destructive editing of keyframe data.
|
||||
*
|
||||
|
@ -162,6 +166,32 @@ static short agrp_keyframes_loop(KeyframeEditData *ked,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_ANIM_BAKLAVA
|
||||
|
||||
/* Loop over all keyframes in the Animation. */
|
||||
static short anim_keyframes_loop(KeyframeEditData *ked,
|
||||
animrig::Animation &anim,
|
||||
animrig::Binding *binding,
|
||||
KeyframeEditFunc key_ok,
|
||||
KeyframeEditFunc key_cb,
|
||||
FcuEditFunc fcu_cb)
|
||||
{
|
||||
if (!binding) {
|
||||
/* Valid situation, and will not have any FCurves. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
Span<FCurve *> fcurves = animrig::fcurves_for_animation(anim, binding->handle);
|
||||
for (FCurve *fcurve : fcurves) {
|
||||
if (ANIM_fcurve_keyframes_loop(ked, fcurve, key_ok, key_cb, fcu_cb)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* This function is used to loop over the keyframe data in an Action */
|
||||
static short act_keyframes_loop(KeyframeEditData *ked,
|
||||
bAction *act,
|
||||
|
@ -385,9 +415,20 @@ short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
|
|||
*/
|
||||
case ALE_GROUP: /* action group */
|
||||
return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb);
|
||||
case ALE_ANIM: { /* Animation data-block. */
|
||||
dr.sybren marked this conversation as resolved
Outdated
Nathan Vegdahl
commented
It wasn't immediately clear to me why this case only executes on a single binding, rather than all bindings within the I think the reason in this case is because this is for when the It wasn't immediately clear to me why this case only executes on a single binding, rather than all bindings within the `Animation` datablock. As it is, it feels redundant with the `ALE_ANIM_BINDING` case below.
I *think* the reason in this case is because this is for when the `Animation` datablock is hierarchically displayed *under* the relevant ID in the channel list, and thus only the single binding to that ID is relevant. Is that correct? If so, it might be worth documenting that in a short comment.
|
||||
#ifdef WITH_ANIM_BAKLAVA
|
||||
/* This assumes that the ALE_ANIM channel is shown in the dopesheet context, underneath the
|
||||
* data-block that owns `ale->adt`. So that means that the loop is limited to the keys that
|
||||
* belong to that binding. */
|
||||
animrig::Animation &anim = static_cast<Animation *>(ale->key_data)->wrap();
|
||||
animrig::Binding *binding = anim.binding_for_handle(ale->adt->binding_handle);
|
||||
return anim_keyframes_loop(ked, anim, binding, key_ok, key_cb, fcu_cb);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
case ALE_ACT: /* action */
|
||||
return act_keyframes_loop(ked, (bAction *)ale->key_data, key_ok, key_cb, fcu_cb);
|
||||
|
||||
case ALE_OB: /* object */
|
||||
return ob_keyframes_loop(ked, ads, (Object *)ale->key_data, key_ok, key_cb, fcu_cb);
|
||||
case ALE_SCE: /* scene */
|
||||
|
@ -423,9 +464,12 @@ short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked,
|
|||
*/
|
||||
case ALE_GROUP: /* action group */
|
||||
return agrp_keyframes_loop(ked, (bActionGroup *)data, key_ok, key_cb, fcu_cb);
|
||||
case ALE_ANIM:
|
||||
/* This function is only used in nlaedit_apply_scale_exec(). Since the NLA has no support for
|
||||
* Animation data-blocks in strips, there is no need to implement this here. */
|
||||
return 0;
|
||||
case ALE_ACT: /* action */
|
||||
return act_keyframes_loop(ked, (bAction *)data, key_ok, key_cb, fcu_cb);
|
||||
|
||||
case ALE_OB: /* object */
|
||||
return ob_keyframes_loop(ked, ads, (Object *)data, key_ok, key_cb, fcu_cb);
|
||||
case ALE_SCE: /* scene */
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include "ED_anim_api.hh"
|
||||
#include "ED_keyframes_keylist.hh"
|
||||
|
||||
#include "ANIM_animation.hh"
|
||||
|
||||
/* *************************** Keyframe Processing *************************** */
|
||||
|
||||
/* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
|
||||
|
@ -1165,6 +1167,25 @@ void action_group_to_keylist(AnimData *adt,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumption: the animation is bound to adt->binding_handle. This assumption will break when we
|
||||
* have things like reference strips, where the strip can reference another binding handle.
|
||||
*/
|
||||
void animation_to_keylist(AnimData *adt,
|
||||
Animation *anim,
|
||||
AnimKeylist *keylist,
|
||||
const int saction_flag,
|
||||
blender::float2 range)
|
||||
{
|
||||
BLI_assert(adt);
|
||||
BLI_assert(anim);
|
||||
BLI_assert(GS(anim->id.name) == ID_AN);
|
||||
|
||||
for (FCurve *fcurve : fcurves_for_animation(anim->wrap(), adt->binding_handle)) {
|
||||
fcurve_to_keylist(adt, fcurve, keylist, saction_flag, range);
|
||||
}
|
||||
}
|
||||
|
||||
void action_to_keylist(AnimData *adt,
|
||||
bAction *act,
|
||||
AnimKeylist *keylist,
|
||||
|
|
|
@ -169,7 +169,7 @@ struct bAnimListElem {
|
|||
*/
|
||||
/** ID block that channel is attached to */
|
||||
ID *id;
|
||||
/** source of the animation data attached to ID block (for convenience) */
|
||||
/** source of the animation data attached to ID block */
|
||||
AnimData *adt;
|
||||
|
||||
/**
|
||||
|
@ -212,6 +212,7 @@ enum eAnim_ChannelType {
|
|||
ANIMTYPE_NLACONTROLS,
|
||||
ANIMTYPE_NLACURVE,
|
||||
|
||||
ANIMTYPE_FILLANIM,
|
||||
ANIMTYPE_FILLACTD,
|
||||
ANIMTYPE_FILLDRIVERS,
|
||||
|
||||
|
@ -271,6 +272,7 @@ enum eAnim_KeyType {
|
|||
ALE_OB, /* Object summary */
|
||||
ALE_ACT, /* Action summary */
|
||||
ALE_GROUP, /* Action Group summary */
|
||||
ALE_ANIM, /* Animation data-block summary. */
|
||||
|
||||
ALE_GREASE_PENCIL_CEL, /* Grease Pencil Cels. */
|
||||
ALE_GREASE_PENCIL_DATA, /* Grease Pencil Cels summary. */
|
||||
|
@ -404,6 +406,7 @@ ENUM_OPERATORS(eAnimFilter_Flags, ANIMFILTER_TMP_IGNORE_ONLYSEL);
|
|||
#define EXPANDED_ACTC(actc) ((actc->flag & ACT_COLLAPSED) == 0)
|
||||
/* 'Sub-AnimData' channels */
|
||||
#define EXPANDED_DRVD(adt) ((adt->flag & ADT_DRIVERS_COLLAPSED) == 0)
|
||||
#define EXPANDED_ADT(adt) ((adt->flag & ADT_UI_EXPANDED) != 0)
|
||||
|
||||
/* Actions (also used for Dopesheet) */
|
||||
/** Action Channel Group. */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "DNA_curve_types.h"
|
||||
|
||||
struct Animation;
|
||||
struct AnimData;
|
||||
struct ChannelDrawList;
|
||||
struct FCurve;
|
||||
|
@ -70,6 +71,13 @@ void ED_add_action_group_channel(ChannelDrawList *draw_list,
|
|||
float ypos,
|
||||
float yscale_fac,
|
||||
int saction_flag);
|
||||
/* Animation Summary.*/
|
||||
void ED_add_animation_channel(ChannelDrawList *channel_list,
|
||||
AnimData *adt,
|
||||
Animation *anim,
|
||||
float ypos,
|
||||
float yscale_fac,
|
||||
int saction_flag);
|
||||
/* Action Summary */
|
||||
void ED_add_action_channel(ChannelDrawList *draw_list,
|
||||
AnimData *adt,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "DNA_curve_types.h"
|
||||
|
||||
struct Animation;
|
||||
struct AnimData;
|
||||
struct CacheFile;
|
||||
struct FCurve;
|
||||
|
@ -161,6 +162,9 @@ void action_group_to_keylist(AnimData *adt,
|
|||
AnimKeylist *keylist,
|
||||
int saction_flag,
|
||||
blender::float2 range);
|
||||
/* Animation */
|
||||
void animation_to_keylist(
|
||||
AnimData *adt, Animation *anim, AnimKeylist *keylist, int saction_flag, blender::float2 range);
|
||||
/* Action */
|
||||
void action_to_keylist(
|
||||
AnimData *adt, bAction *act, AnimKeylist *keylist, int saction_flag, blender::float2 range);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
/* Types --------------------------------------------------------------- */
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
@ -221,6 +222,7 @@ static void draw_backdrops(bAnimContext *ac, ListBase &anim_data, View2D *v2d, u
|
|||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLACTD:
|
||||
case ANIMTYPE_FILLANIM:
|
||||
case ANIMTYPE_DSSKEY:
|
||||
case ANIMTYPE_DSWOR: {
|
||||
immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
|
||||
|
@ -366,6 +368,14 @@ static void draw_keyframes(bAnimContext *ac,
|
|||
scale_factor,
|
||||
action_flag);
|
||||
break;
|
||||
case ALE_ANIM:
|
||||
ED_add_animation_channel(draw_list,
|
||||
adt,
|
||||
static_cast<Animation *>(ale->key_data),
|
||||
ycenter,
|
||||
scale_factor,
|
||||
action_flag);
|
||||
break;
|
||||
case ALE_ACT:
|
||||
ED_add_action_channel(draw_list,
|
||||
adt,
|
||||
|
|
|
@ -112,6 +112,11 @@ static void actkeys_list_element_to_keylist(bAnimContext *ac,
|
|||
ob_to_keylist(ads, ob, keylist, 0, range);
|
||||
break;
|
||||
}
|
||||
case ALE_ANIM: {
|
||||
Animation *anim = (Animation *)ale->key_data;
|
||||
animation_to_keylist(adt, anim, keylist, 0, range);
|
||||
break;
|
||||
}
|
||||
case ALE_ACT: {
|
||||
bAction *act = (bAction *)ale->key_data;
|
||||
action_to_keylist(adt, act, keylist, 0, range);
|
||||
|
|
|
@ -261,6 +261,9 @@ static int mouse_nla_tracks(bContext *C, bAnimContext *ac, int track_index, shor
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLANIM:
|
||||
/* The NLA doesn't support Animation data-blocks. */
|
||||
break;
|
||||
default:
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("Error: Invalid track type in mouse_nla_tracks()\n");
|
||||
|
|
|
@ -1224,6 +1224,10 @@ typedef enum eAnimData_Flag {
|
|||
|
||||
/** F-Curves from this AnimData block are always visible. */
|
||||
ADT_CURVES_ALWAYS_VISIBLE = (1 << 17),
|
||||
|
||||
/** Animation pointer to by this AnimData block is expanded in UI. This is stored on the AnimData
|
||||
* so that each user of the Animation can have its own expansion/contraction state. */
|
||||
ADT_UI_EXPANDED = (1 << 18),
|
||||
} eAnimData_Flag;
|
||||
|
||||
/* Base Struct for Anim ------------------------------------- */
|
||||
|
@ -1272,6 +1276,9 @@ typedef struct Animation {
|
|||
int binding_array_num;
|
||||
int32_t last_binding_handle;
|
||||
|
||||
uint8_t flag;
|
||||
uint8_t _pad0[7];
|
||||
|
||||
#ifdef __cplusplus
|
||||
blender::animrig::Animation &wrap();
|
||||
const blender::animrig::Animation &wrap() const;
|
||||
|
|
Loading…
Reference in New Issue
Love all these replacements. So much cleaner.