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:
authorJoshua Leung <aligorith@gmail.com>2018-05-29 12:47:47 +0300
committerJoshua Leung <aligorith@gmail.com>2018-06-02 21:03:29 +0300
commitd1e3ba22a03c5b30b39acbf6ea66978379e116d6 (patch)
tree5645006a560d5517a92e8e70c6026d82926d9e5c
parent6de656b4f2ac66922d34bedbeb8f857bc878c5ae (diff)
Collections: Initial support for animating/driving collection properties (T55233)tmp-CollectionsAnim
(Just committing this now to a temp branch so that I can continue working on this from another machine later. This is a re-based+squashed, re-pushed version of what I just pushed earlier, but now based on current 2.8 code, not from several days ago) Rationale: The Spring team needs a way to hide objects from the viewport, so that parts of the rig can be enabled/disabled per shot. An example of this is how the cornea meshes are typically hidden from the viewport so that the animators can see the irises, and hence, where the character is looking. (Another reason we may want this in future is to make it so that a bunch of objects/rigs can be keyframed together in the same action, making it easier to manage their actions) Status: * Currently all necessary data and animation editor support changes should be in place and working. Hopefully I haven't missed any - the checklist may need updating for 2.8 * Depsgraph support however is still incomplete. We still need to figure out what needs to happen with the animated values to make objects actually appear/disappear when triggered via the animation system, just like they do now from the UIwip
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c10
-rw-r--r--source/blender/blenkernel/intern/collection.c4
-rw-r--r--source/blender/blenloader/intern/readfile.c8
-rw-r--r--source/blender/blenloader/intern/writefile.c4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc2
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c108
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c34
-rw-r--r--source/blender/editors/animation/anim_filter.c123
-rw-r--r--source/blender/editors/include/ED_anim_api.h4
-rw-r--r--source/blender/editors/space_action/action_draw.c1
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c1
-rw-r--r--source/blender/editors/space_nla/nla_channels.c19
-rw-r--r--source/blender/makesdna/DNA_group_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_group.c3
15 files changed, 324 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index e5a68fa7476..22db91190a5 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -104,6 +104,7 @@ bool id_type_can_have_animdata(const short id_type)
case ID_MSK:
case ID_GD:
case ID_CF:
+ case ID_GR:
return true;
/* no AnimData */
@@ -1135,6 +1136,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u
/* masks */
ANIMDATA_IDS_CB(mainptr->mask.first);
+ /* collections */
+ ANIMDATA_IDS_CB(mainptr->collection.first);
+
/* worlds */
ANIMDATA_NODETREE_IDS_CB(mainptr->world.first, World);
@@ -1234,6 +1238,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, const char *prefix, const cha
/* worlds */
RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World);
+ /* collections */
+ RENAMEFIX_ANIM_IDS(mainptr->collection.first);
+
/* linestyles */
RENAMEFIX_ANIM_IDS(mainptr->linestyle.first);
@@ -2935,6 +2942,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, Scene
/* masks */
EVAL_ANIM_IDS(main->mask.first, ADT_RECALC_ANIM);
+ /* collections */
+ EVAL_ANIM_IDS(main->collection.first, ADT_RECALC_ANIM);
+
/* worlds */
EVAL_ANIM_NODETREE_IDS(main->world.first, World, ADT_RECALC_ANIM);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index c4709a32f78..295b7d39f13 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -35,6 +35,7 @@
#include "BLT_translation.h"
#include "BLI_string_utils.h"
+#include "BKE_animsys.h"
#include "BKE_collection.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
@@ -112,7 +113,8 @@ Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const
/** Free (or release) any data used by this collection (does not free the collection itself). */
void BKE_collection_free(Collection *collection)
{
- /* No animdata here. */
+ BKE_animdata_free(&collection->id, false);
+
BKE_previewimg_free(&collection->preview);
BLI_freelistN(&collection->gobject);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index d2542e977e3..8f0c470929e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5679,6 +5679,9 @@ static void direct_link_collection(FileData *fd, Collection *collection)
link_list(fd, &collection->gobject);
link_list(fd, &collection->children);
+ collection->adt = newdataadr(fd, collection->adt);
+ direct_link_animdata(fd, collection->adt);
+
collection->preview = direct_link_preview_image(fd, collection->preview);
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
@@ -5733,6 +5736,7 @@ static void lib_link_collection(FileData *fd, Main *main)
if (collection->id.tag & LIB_TAG_NEED_LINK) {
collection->id.tag &= ~LIB_TAG_NEED_LINK;
IDP_LibLinkProperty(collection->id.properties, fd);
+ lib_link_animdata(fd, &collection->id, collection->adt);
#ifdef USE_COLLECTION_COMPAT_28
if (collection->collection) {
@@ -9272,6 +9276,10 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting
static void expand_collection(FileData *fd, Main *mainvar, Collection *collection)
{
+ if (collection->adt) {
+ expand_animdata(fd, mainvar, collection->adt);
+ }
+
for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
expand_doit(fd, mainvar, cob->ob);
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index de1699e24b7..e47a5ec2823 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2376,6 +2376,10 @@ static void write_collection(WriteData *wd, Collection *collection)
/* write LibData */
writestruct(wd, ID_GR, Collection, 1, collection);
write_iddata(wd, &collection->id);
+
+ if (collection->adt) {
+ write_animdata(wd, collection->adt);
+ }
write_collection_nolib(wd, collection);
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 5867e278c78..a746b00b548 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -435,6 +435,8 @@ void DepsgraphNodeBuilder::build_collection(Collection *collection)
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
build_collection(child->collection);
}
+ /* Build animation data. */
+ build_animdata(&collection->id);
add_id_node(&collection->id);
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index d5ea8103742..acb599ce46e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -444,6 +444,8 @@ void DepsgraphRelationBuilder::build_collection(Object *object, Collection *coll
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
build_collection(NULL, child->collection);
}
+ /* Animation data - should only need one set of relations per collection, not once per instance */
+ build_animdata(&collection->id);
}
if (object != NULL) {
const ListBase group_objects = BKE_collection_object_cache_get(collection);
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index d48798ece97..23009ae5385 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -626,6 +626,111 @@ static bAnimChannelType ACF_SCENE =
acf_scene_setting_ptr /* pointer for setting */
};
+/* Collection ------------------------------------------- */
+
+// TODO: just get this from RNA?
+static int acf_collection_icon(bAnimListElem *UNUSED(ale))
+{
+ return ICON_GROUP;
+}
+
+/* check if some setting exists for this channel */
+static bool acf_collection_setting_valid(bAnimContext *ac, bAnimListElem *UNUSED(ale), eAnimChannel_Settings setting)
+{
+ switch (setting) {
+ /* muted only in NLA */
+ case ACHANNEL_SETTING_MUTE:
+ return ((ac) && (ac->spacetype == SPACE_NLA));
+
+ /* visible only in Graph Editor */
+ case ACHANNEL_SETTING_VISIBLE:
+ return ((ac) && (ac->spacetype == SPACE_IPO));
+
+ /* only select and expand supported otherwise */
+ case ACHANNEL_SETTING_SELECT:
+ case ACHANNEL_SETTING_EXPAND:
+ return true;
+
+ case ACHANNEL_SETTING_ALWAYS_VISIBLE:
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_collection_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settings setting, bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return COLLECTION_DS_SELECTED;
+
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ *neg = true;
+ return COLLECTION_DS_COLLAPSED;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ default: /* unsupported */
+ return 0;
+ }
+}
+
+/* get pointer to the setting */
+static void *acf_collection_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+{
+ Collection *collection = (Collection *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return GET_ACF_FLAG_PTR(collection->flag, type);
+
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(collection->flag, type);
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (collection->adt)
+ return GET_ACF_FLAG_PTR(collection->adt->flag, type);
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* collection type define */
+static bAnimChannelType ACF_COLLECTION =
+{
+ "Collection", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_root_color, /* backdrop color */
+ acf_generic_root_backdrop, /* backdrop */
+ acf_generic_indention_0, /* indent level */
+ NULL, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idblock_name_prop, /* name prop */
+ acf_collection_icon, /* icon */
+
+ acf_collection_setting_valid, /* has setting */
+ acf_collection_setting_flag, /* flag for setting */
+ acf_collection_setting_ptr /* pointer for setting */
+};
+
/* Object ------------------------------------------- */
static int acf_object_icon(bAnimListElem *ale)
@@ -3567,8 +3672,9 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_SUMMARY; /* Motion Summary */
animchannelTypeInfo[type++] = &ACF_SCENE; /* Scene */
+ animchannelTypeInfo[type++] = &ACF_COLLECTION; /* Collection */
animchannelTypeInfo[type++] = &ACF_OBJECT; /* Object */
- animchannelTypeInfo[type++] = &ACF_GROUP; /* Group */
+ animchannelTypeInfo[type++] = &ACF_GROUP; /* ActionGroup */
animchannelTypeInfo[type++] = &ACF_FCURVE; /* F-Curve */
animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 6d9a2d3b2b7..5b174d6506e 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -280,6 +280,10 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
if (ale->flag & SCE_DS_SELECTED)
sel = ACHANNEL_SETFLAG_CLEAR;
break;
+ case ANIMTYPE_COLLECTION:
+ if (ale->flag & COLLECTION_DS_SELECTED)
+ sel = ACHANNEL_SETFLAG_CLEAR;
+ break;
case ANIMTYPE_OBJECT:
#if 0 /* for now, do not take object selection into account, since it gets too annoying */
if (ale->flag & SELECT)
@@ -354,6 +358,17 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
}
break;
}
+ case ANIMTYPE_COLLECTION:
+ {
+ Collection *collection = (Collection *)ale->data;
+
+ ACHANNEL_SET_FLAG(collection, sel, COLLECTION_DS_SELECTED);
+
+ if (collection->adt) {
+ ACHANNEL_SET_FLAG(collection, sel, ADT_UI_SELECTED);
+ }
+ break;
+ }
case ANIMTYPE_OBJECT:
{
#if 0 /* for now, do not take object selection into account, since it gets too annoying */
@@ -2681,6 +2696,25 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
+ case ANIMTYPE_COLLECTION:
+ {
+ Collection *collection = (Collection *)ale->data;
+ AnimData *adt = collection->adt;
+
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ collection->flag ^= COLLECTION_DS_SELECTED;
+ if (adt) adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ collection->flag |= COLLECTION_DS_SELECTED;
+ if (adt) adt->flag |= ADT_UI_SELECTED;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
case ANIMTYPE_OBJECT:
{
#if 0
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 0fd97dfb182..1cda7e77dc5 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -614,6 +614,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
break;
}
+ case ANIMTYPE_COLLECTION:
+ {
+ Collection *collection = (Collection *)data;
+
+ ale->flag = collection->flag;
+
+ /* XXX: Nothing to include here for now... to be populated later */
+ ale->key_data = NULL;
+ ale->datatype = ALE_NONE;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
case ANIMTYPE_OBJECT:
{
Base *base = (Base *)data;
@@ -2630,6 +2643,102 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
return items;
}
+/* animation channels for collection */
+static size_t animdata_filter_ds_collection(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Collection *collection, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ AnimData *adt = collection->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(collection,
+ { /* AnimData - no channel, but consider data */},
+ { /* NLA - no channel, but consider data */},
+ { /* Drivers */
+ type = ANIMTYPE_FILLDRIVERS;
+ cdata = adt;
+ expanded = EXPANDED_DRVD(adt);
+ },
+ { /* NLA Strip Controls - no dedicated channel for now (XXX) */ },
+ { /* Keyframes */
+ type = ANIMTYPE_FILLACTD;
+ cdata = adt->action;
+ expanded = EXPANDED_ACTC(adt->action);
+ });
+
+ /* add scene-level animation channels */
+ BEGIN_ANIMFILTER_SUBCHANNELS(expanded)
+ {
+ /* animation data filtering */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, (ID *)collection, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* 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, collection);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
+/* collection animation */
+static size_t animdata_filter_dopesheet_collection(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Collection *collection, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* filter data contained under collection first */
+ BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_COLLECTIONC(collection))
+ {
+ /* Action, Drivers, or NLA for Collection itself */
+ //if ((ads->filterflag & ADS_FILTER_NOSCE) == 0) {
+ tmp_items += animdata_filter_ds_collection(ac, &tmp_data, ads, collection, filter_mode);
+ //}
+
+ /* TODO: Allow showing for stuff inside collection? */
+ }
+ 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((collection->flag & COLLECTION_DS_SELECTED))) {
+ /* NOTE: active-status doesn't matter for this! */
+ ANIMCHANNEL_NEW_CHANNEL(collection, ANIMTYPE_COLLECTION, collection);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added */
+ return items;
+}
+
static size_t animdata_filter_ds_world(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, World *wo, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
@@ -2729,7 +2838,7 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
size_t tmp_items = 0;
size_t items = 0;
- /* filter data contained under object first */
+ /* filter data contained under scene first */
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_SCEC(sce))
{
bNodeTree *ntree = sce->nodetree;
@@ -2969,7 +3078,13 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
/* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
-
+
+ /* collection animation */
+ /* XXX: Just list all collections for now */
+ for (Collection *collection = G.main->collection.first; collection; collection = collection->id.next) {
+ items += animdata_filter_dopesheet_collection(ac, anim_data, ads, collection, filter_mode);
+ }
+
/* If filtering for channel drawing, we want the objects in alphabetical order,
* to make it easier to predict where items are in the hierarchy
* - This order only really matters if we need to show all channels in the list (e.g. for drawing)
@@ -3074,6 +3189,10 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
case ANIMTYPE_SCENE:
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, channel->data, filter_mode);
break;
+
+ case ANIMTYPE_COLLECTION:
+ items += animdata_filter_dopesheet_collection(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);
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index a25b1b84cc5..7474b4a72bd 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -155,6 +155,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_SUMMARY,
ANIMTYPE_SCENE,
+ ANIMTYPE_COLLECTION,
ANIMTYPE_OBJECT,
ANIMTYPE_GROUP,
ANIMTYPE_FCURVE,
@@ -281,6 +282,9 @@ typedef enum eAnimFilter_Flags {
/* 'Sub-Scene' channels (flags stored in Data block) */
#define FILTER_WOR_SCED(wo) (CHECK_TYPE_INLINE(wo, World *), (wo->flag & WO_DS_EXPAND))
#define FILTER_LS_SCED(linestyle) ((linestyle->flag & LS_DS_EXPAND))
+/* 'Collection' channels */
+#define SEL_COLLECTIONC(collection) (CHECK_TYPE_INLINE(collection, Collection *), ((collection->flag & COLLECTION_DS_SELECTED)))
+#define EXPANDED_COLLECTIONC(collection) (CHECK_TYPE_INLINE(collection, Collection *), ((collection->flag & COLLECTION_DS_COLLAPSED) == 0))
/* 'Object' channels */
#define SEL_OBJC(base) (CHECK_TYPE_INLINE(base, Base *), ((base->flag & SELECT)))
#define EXPANDED_OBJC(ob) (CHECK_TYPE_INLINE(ob, Object *), ((ob->nlaflag & OB_ADS_COLLAPSED) == 0))
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 3e9b742480a..8ce2288dbd3 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -243,6 +243,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
break;
}
case ANIMTYPE_SCENE:
+ case ANIMTYPE_COLLECTION:
case ANIMTYPE_OBJECT:
{
immUniformColor3ubvAlpha(col1b, sel ? 0x45 : 0x22);
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index c173aac1a26..3c61fb6fbcf 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -127,6 +127,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
break;
}
case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */
+ case ANIMTYPE_COLLECTION:
case ANIMTYPE_OBJECT:
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 9b7a49ec624..b8588842ece 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -122,6 +122,25 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
+ case ANIMTYPE_COLLECTION:
+ {
+ Collection *collection = (Collection *)ale->data;
+ AnimData *adt = collection->adt;
+
+ /* set selection status */
+ if (selectmode == SELECT_INVERT) {
+ /* swap select */
+ collection->flag ^= COLLECTION_DS_SELECTED;
+ if (adt) adt->flag ^= ADT_UI_SELECTED;
+ }
+ else {
+ collection->flag |= COLLECTION_DS_SELECTED;
+ if (adt) adt->flag |= ADT_UI_SELECTED;
+ }
+
+ notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
+ break;
+ }
case ANIMTYPE_OBJECT:
{
ViewLayer *view_layer = ac->view_layer;
diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h
index 3b947caf59c..be773233a79 100644
--- a/source/blender/makesdna/DNA_group_types.h
+++ b/source/blender/makesdna/DNA_group_types.h
@@ -40,6 +40,7 @@
struct Object;
struct Collection;
+struct AnimData;
typedef struct CollectionObject {
struct CollectionObject *next, *prev;
@@ -55,6 +56,7 @@ typedef struct CollectionChild {
typedef struct Collection {
ID id;
+ struct AnimData *adt;
ListBase gobject; /* CollectionObject */
ListBase children; /* CollectionChild */
@@ -89,6 +91,9 @@ enum {
COLLECTION_RESTRICT_RENDER = (1 << 3), /* Hidden in renders. */
COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */
COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */
+
+ COLLECTION_DS_SELECTED = (1 << 10), /* Channel is selected in animation editors */
+ COLLECTION_DS_COLLAPSED = (1 << 11), /* Channel is collapsed in animation editors (defaults open) */
};
#endif /* __DNA_GROUP_TYPES_H__ */
diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c
index 116c0bc4a26..74e23f147eb 100644
--- a/source/blender/makesrna/intern/rna_group.c
+++ b/source/blender/makesrna/intern/rna_group.c
@@ -275,6 +275,9 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, 1);
RNA_def_property_ui_text(prop, "Restrict Render", "Hide collection objects in renders");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update");
+
+ /* Animation Data */
+ rna_def_animdata_common(srna);
}
#endif