DNA: move Collection members into their own Runtime struct

Also add static assert that COLLECTION_COLOR_TOT has the correct number
of items in the enum.
This commit is contained in:
Campbell Barton 2023-01-18 13:47:00 +11:00
parent 9179362e7b
commit 44dd3308a5
12 changed files with 121 additions and 98 deletions

View File

@ -574,7 +574,8 @@ static void loose_data_instantiate_obdata_preprocess(
* (return false). */ * (return false). */
static bool loose_data_instantiate_collection_parents_check_recursive(Collection *collection) static bool loose_data_instantiate_collection_parents_check_recursive(Collection *collection)
{ {
for (CollectionParent *parent_collection = collection->parents.first; parent_collection != NULL; for (CollectionParent *parent_collection = collection->runtime.parents.first;
parent_collection != NULL;
parent_collection = parent_collection->next) { parent_collection = parent_collection->next) {
if ((parent_collection->collection->id.tag & LIB_TAG_DOIT) != 0) { if ((parent_collection->collection->id.tag & LIB_TAG_DOIT) != 0) {
return true; return true;

View File

@ -114,12 +114,12 @@ static void collection_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons
collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE; collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED; collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
BLI_listbase_clear(&collection_dst->object_cache); BLI_listbase_clear(&collection_dst->runtime.object_cache);
BLI_listbase_clear(&collection_dst->object_cache_instanced); BLI_listbase_clear(&collection_dst->runtime.object_cache_instanced);
BLI_listbase_clear(&collection_dst->gobject); BLI_listbase_clear(&collection_dst->gobject);
BLI_listbase_clear(&collection_dst->children); BLI_listbase_clear(&collection_dst->children);
BLI_listbase_clear(&collection_dst->parents); BLI_listbase_clear(&collection_dst->runtime.parents);
LISTBASE_FOREACH (CollectionChild *, child, &collection_src->children) { LISTBASE_FOREACH (CollectionChild *, child, &collection_src->children) {
collection_child_add(collection_dst, child->collection, flag, false); collection_child_add(collection_dst, child->collection, flag, false);
@ -138,7 +138,7 @@ static void collection_free_data(ID *id)
BLI_freelistN(&collection->gobject); BLI_freelistN(&collection->gobject);
BLI_freelistN(&collection->children); BLI_freelistN(&collection->children);
BLI_freelistN(&collection->parents); BLI_freelistN(&collection->runtime.parents);
BKE_collection_object_cache_free(collection); BKE_collection_object_cache_free(collection);
} }
@ -148,7 +148,7 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
Collection *collection = (Collection *)id; Collection *collection = (Collection *)id;
BKE_LIB_FOREACHID_PROCESS_ID( BKE_LIB_FOREACHID_PROCESS_ID(
data, collection->owner_id, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF); data, collection->runtime.owner_id, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF);
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, cob->ob, IDWALK_CB_USER); BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, cob->ob, IDWALK_CB_USER);
@ -157,7 +157,7 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_LIB_FOREACHID_PROCESS_IDSUPER( BKE_LIB_FOREACHID_PROCESS_IDSUPER(
data, child->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_USER); data, child->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_USER);
} }
LISTBASE_FOREACH (CollectionParent *, parent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, parent, &collection->runtime.parents) {
/* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad
* anyway... */ * anyway... */
const int cb_flag = ((parent->collection != NULL && const int cb_flag = ((parent->collection != NULL &&
@ -178,11 +178,12 @@ static ID **collection_owner_pointer_get(ID *id)
Collection *master_collection = (Collection *)id; Collection *master_collection = (Collection *)id;
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0); BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
BLI_assert(master_collection->owner_id != NULL); BLI_assert(master_collection->runtime.owner_id != NULL);
BLI_assert(GS(master_collection->owner_id->name) == ID_SCE); BLI_assert(GS(master_collection->runtime.owner_id->name) == ID_SCE);
BLI_assert(((Scene *)master_collection->owner_id)->master_collection == master_collection); BLI_assert(((Scene *)master_collection->runtime.owner_id)->master_collection ==
master_collection);
return &master_collection->owner_id; return &master_collection->runtime.owner_id;
} }
void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection) void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection)
@ -208,10 +209,10 @@ static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_a
/* Clean up, important in undo case to reduce false detection of changed data-blocks. */ /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED; collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
collection->tag = 0; collection->runtime.tag = 0;
BLI_listbase_clear(&collection->object_cache); BLI_listbase_clear(&collection->runtime.object_cache);
BLI_listbase_clear(&collection->object_cache_instanced); BLI_listbase_clear(&collection->runtime.object_cache_instanced);
BLI_listbase_clear(&collection->parents); BLI_listbase_clear(&collection->runtime.parents);
/* write LibData */ /* write LibData */
BLO_write_id_struct(writer, Collection, id_address, &collection->id); BLO_write_id_struct(writer, Collection, id_address, &collection->id);
@ -258,7 +259,7 @@ void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collect
} }
collection->id.flag |= LIB_EMBEDDED_DATA; collection->id.flag |= LIB_EMBEDDED_DATA;
} }
collection->owner_id = owner_id; collection->runtime.owner_id = owner_id;
BLO_read_list(reader, &collection->gobject); BLO_read_list(reader, &collection->gobject);
BLO_read_list(reader, &collection->children); BLO_read_list(reader, &collection->children);
@ -268,10 +269,10 @@ void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collect
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED; collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
collection->tag = 0; collection->runtime.tag = 0;
BLI_listbase_clear(&collection->object_cache); BLI_listbase_clear(&collection->runtime.object_cache);
BLI_listbase_clear(&collection->object_cache_instanced); BLI_listbase_clear(&collection->runtime.object_cache_instanced);
BLI_listbase_clear(&collection->parents); BLI_listbase_clear(&collection->runtime.parents);
#ifdef USE_COLLECTION_COMPAT_28 #ifdef USE_COLLECTION_COMPAT_28
/* This runs before the very first doversion. */ /* This runs before the very first doversion. */
@ -543,7 +544,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
else { else {
/* Link child collections into parent collection. */ /* Link child collections into parent collection. */
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
Collection *parent = cparent->collection; Collection *parent = cparent->collection;
collection_child_add(parent, child->collection, 0, true); collection_child_add(parent, child->collection, 0, true);
} }
@ -552,7 +553,7 @@ bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
CollectionObject *cob = collection->gobject.first; CollectionObject *cob = collection->gobject.first;
while (cob != NULL) { while (cob != NULL) {
/* Link child object into parent collections. */ /* Link child object into parent collections. */
LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
Collection *parent = cparent->collection; Collection *parent = cparent->collection;
collection_object_add(bmain, parent, cob->ob, 0, true); collection_object_add(bmain, parent, cob->ob, 0, true);
} }
@ -816,13 +817,13 @@ ListBase BKE_collection_object_cache_get(Collection *collection)
BLI_mutex_lock(&cache_lock); BLI_mutex_lock(&cache_lock);
if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) { if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
collection_object_cache_fill(&collection->object_cache, collection, 0, false); collection_object_cache_fill(&collection->runtime.object_cache, collection, 0, false);
collection->flag |= COLLECTION_HAS_OBJECT_CACHE; collection->flag |= COLLECTION_HAS_OBJECT_CACHE;
} }
BLI_mutex_unlock(&cache_lock); BLI_mutex_unlock(&cache_lock);
} }
return collection->object_cache; return collection->runtime.object_cache;
} }
ListBase BKE_collection_object_cache_instanced_get(Collection *collection) ListBase BKE_collection_object_cache_instanced_get(Collection *collection)
@ -832,13 +833,14 @@ ListBase BKE_collection_object_cache_instanced_get(Collection *collection)
BLI_mutex_lock(&cache_lock); BLI_mutex_lock(&cache_lock);
if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE_INSTANCED)) { if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE_INSTANCED)) {
collection_object_cache_fill(&collection->object_cache_instanced, collection, 0, true); collection_object_cache_fill(
&collection->runtime.object_cache_instanced, collection, 0, true);
collection->flag |= COLLECTION_HAS_OBJECT_CACHE_INSTANCED; collection->flag |= COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
} }
BLI_mutex_unlock(&cache_lock); BLI_mutex_unlock(&cache_lock);
} }
return collection->object_cache_instanced; return collection->runtime.object_cache_instanced;
} }
static void collection_object_cache_free(Collection *collection) static void collection_object_cache_free(Collection *collection)
@ -846,10 +848,10 @@ static void collection_object_cache_free(Collection *collection)
/* Clear own cache an for all parents, since those are affected by changes as well. */ /* Clear own cache an for all parents, since those are affected by changes as well. */
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE; collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED; collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
BLI_freelistN(&collection->object_cache); BLI_freelistN(&collection->runtime.object_cache);
BLI_freelistN(&collection->object_cache_instanced); BLI_freelistN(&collection->runtime.object_cache_instanced);
LISTBASE_FOREACH (CollectionParent *, parent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, parent, &collection->runtime.parents) {
collection_object_cache_free(parent->collection); collection_object_cache_free(parent->collection);
} }
} }
@ -884,7 +886,7 @@ Collection *BKE_collection_master_add(Scene *scene)
Collection *master_collection = BKE_libblock_alloc( Collection *master_collection = BKE_libblock_alloc(
NULL, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN); NULL, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN);
master_collection->id.flag |= LIB_EMBEDDED_DATA; master_collection->id.flag |= LIB_EMBEDDED_DATA;
master_collection->owner_id = &scene->id; master_collection->runtime.owner_id = &scene->id;
master_collection->flag |= COLLECTION_IS_MASTER; master_collection->flag |= COLLECTION_IS_MASTER;
master_collection->color_tag = COLLECTION_COLOR_NONE; master_collection->color_tag = COLLECTION_COLOR_NONE;
@ -1024,7 +1026,7 @@ static void collection_tag_update_parent_recursive(Main *bmain,
DEG_id_tag_update_ex(bmain, &collection->id, flag); DEG_id_tag_update_ex(bmain, &collection->id, flag);
LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->runtime.parents) {
if (collection_parent->collection->flag & COLLECTION_IS_MASTER) { if (collection_parent->collection->flag & COLLECTION_IS_MASTER) {
/* We don't care about scene/master collection here. */ /* We don't care about scene/master collection here. */
continue; continue;
@ -1045,7 +1047,7 @@ static Collection *collection_parent_editable_find_recursive(const ViewLayer *vi
return NULL; return NULL;
} }
LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->runtime.parents) {
if (!ID_IS_LINKED(collection_parent->collection) && if (!ID_IS_LINKED(collection_parent->collection) &&
!ID_IS_OVERRIDE_LIBRARY(collection_parent->collection)) { !ID_IS_OVERRIDE_LIBRARY(collection_parent->collection)) {
if (view_layer != NULL && if (view_layer != NULL &&
@ -1344,9 +1346,9 @@ static void collection_null_children_remove(Collection *collection)
static void collection_missing_parents_remove(Collection *collection) static void collection_missing_parents_remove(Collection *collection)
{ {
LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &collection->parents) { LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &collection->runtime.parents) {
if ((parent->collection == NULL) || !collection_find_child(parent->collection, collection)) { if ((parent->collection == NULL) || !collection_find_child(parent->collection, collection)) {
BLI_freelinkN(&collection->parents, parent); BLI_freelinkN(&collection->runtime.parents, parent);
} }
} }
} }
@ -1380,11 +1382,11 @@ void BKE_collections_child_remove_nulls(Main *bmain,
} }
} }
else { else {
LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &child_collection->parents) { LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &child_collection->runtime.parents) {
collection_null_children_remove(parent->collection); collection_null_children_remove(parent->collection);
if (!collection_find_child(parent->collection, child_collection)) { if (!collection_find_child(parent->collection, child_collection)) {
BLI_freelinkN(&child_collection->parents, parent); BLI_freelinkN(&child_collection->runtime.parents, parent);
} }
} }
} }
@ -1420,7 +1422,7 @@ bool BKE_collection_is_in_scene(Collection *collection)
return true; return true;
} }
LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
if (BKE_collection_is_in_scene(cparent->collection)) { if (BKE_collection_is_in_scene(cparent->collection)) {
return true; return true;
} }
@ -1474,7 +1476,7 @@ bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection)
collection = new_ancestor; collection = new_ancestor;
} }
LISTBASE_FOREACH (CollectionParent *, parent, &new_ancestor->parents) { LISTBASE_FOREACH (CollectionParent *, parent, &new_ancestor->runtime.parents) {
if (BKE_collection_cycle_find(parent->collection, collection)) { if (BKE_collection_cycle_find(parent->collection, collection)) {
return true; return true;
} }
@ -1514,7 +1516,7 @@ static bool collection_cycle_fix_recursive(Main *bmain,
{ {
bool cycles_found = false; bool cycles_found = false;
LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &parent_collection->parents) { LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &parent_collection->runtime.parents) {
if (BKE_collection_cycle_find(parent->collection, collection)) { if (BKE_collection_cycle_find(parent->collection, collection)) {
BKE_collection_child_remove(bmain, parent->collection, parent_collection); BKE_collection_child_remove(bmain, parent->collection, parent_collection);
cycles_found = true; cycles_found = true;
@ -1560,7 +1562,7 @@ bool BKE_collection_has_collection(const Collection *parent, const Collection *c
static CollectionParent *collection_find_parent(Collection *child, Collection *collection) static CollectionParent *collection_find_parent(Collection *child, Collection *collection)
{ {
return BLI_findptr(&child->parents, collection, offsetof(CollectionParent, collection)); return BLI_findptr(&child->runtime.parents, collection, offsetof(CollectionParent, collection));
} }
static bool collection_child_add(Collection *parent, static bool collection_child_add(Collection *parent,
@ -1584,7 +1586,7 @@ static bool collection_child_add(Collection *parent,
if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent"); CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
cparent->collection = parent; cparent->collection = parent;
BLI_addtail(&collection->parents, cparent); BLI_addtail(&collection->runtime.parents, cparent);
} }
if (add_us) { if (add_us) {
@ -1604,7 +1606,7 @@ static bool collection_child_remove(Collection *parent, Collection *collection)
} }
CollectionParent *cparent = collection_find_parent(collection, parent); CollectionParent *cparent = collection_find_parent(collection, parent);
BLI_freelinkN(&collection->parents, cparent); BLI_freelinkN(&collection->runtime.parents, cparent);
BLI_freelinkN(&parent->children, child); BLI_freelinkN(&parent->children, child);
id_us_min(&collection->id); id_us_min(&collection->id);
@ -1664,19 +1666,19 @@ void BKE_collection_parent_relations_rebuild(Collection *collection)
BLI_assert(collection_find_parent(child->collection, collection) == NULL); BLI_assert(collection_find_parent(child->collection, collection) == NULL);
CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), __func__); CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), __func__);
cparent->collection = collection; cparent->collection = collection;
BLI_addtail(&child->collection->parents, cparent); BLI_addtail(&child->collection->runtime.parents, cparent);
} }
} }
static void collection_parents_rebuild_recursive(Collection *collection) static void collection_parents_rebuild_recursive(Collection *collection)
{ {
/* A same collection may be child of several others, no need to process it more than once. */ /* A same collection may be child of several others, no need to process it more than once. */
if ((collection->tag & COLLECTION_TAG_RELATION_REBUILD) == 0) { if ((collection->runtime.tag & COLLECTION_TAG_RELATION_REBUILD) == 0) {
return; return;
} }
BKE_collection_parent_relations_rebuild(collection); BKE_collection_parent_relations_rebuild(collection);
collection->tag &= ~COLLECTION_TAG_RELATION_REBUILD; collection->runtime.tag &= ~COLLECTION_TAG_RELATION_REBUILD;
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) { LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
/* See comment above in `BKE_collection_parent_relations_rebuild`. */ /* See comment above in `BKE_collection_parent_relations_rebuild`. */
@ -1691,9 +1693,9 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain)
{ {
/* Only collections not in bmain (master ones in scenes) have no parent... */ /* Only collections not in bmain (master ones in scenes) have no parent... */
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
BLI_freelistN(&collection->parents); BLI_freelistN(&collection->runtime.parents);
collection->tag |= COLLECTION_TAG_RELATION_REBUILD; collection->runtime.tag |= COLLECTION_TAG_RELATION_REBUILD;
} }
/* Scene's master collections will be 'root' parent of most of our collections, so start with /* Scene's master collections will be 'root' parent of most of our collections, so start with
@ -1702,8 +1704,8 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain)
/* This function can be called from readfile.c, when this pointer is not guaranteed to be NULL. /* This function can be called from readfile.c, when this pointer is not guaranteed to be NULL.
*/ */
if (scene->master_collection != NULL) { if (scene->master_collection != NULL) {
BLI_assert(BLI_listbase_is_empty(&scene->master_collection->parents)); BLI_assert(BLI_listbase_is_empty(&scene->master_collection->runtime.parents));
scene->master_collection->tag |= COLLECTION_TAG_RELATION_REBUILD; scene->master_collection->runtime.tag |= COLLECTION_TAG_RELATION_REBUILD;
collection_parents_rebuild_recursive(scene->master_collection); collection_parents_rebuild_recursive(scene->master_collection);
} }
} }
@ -1711,7 +1713,7 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain)
/* We may have parent chains outside of scene's master_collection context? At least, readfile's /* We may have parent chains outside of scene's master_collection context? At least, readfile's
* lib_link_collection_data() seems to assume that, so do the same here. */ * lib_link_collection_data() seems to assume that, so do the same here. */
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
if (collection->tag & COLLECTION_TAG_RELATION_REBUILD) { if (collection->runtime.tag & COLLECTION_TAG_RELATION_REBUILD) {
/* NOTE: we do not have easy access to 'which collections is root' info in that case, which /* NOTE: we do not have easy access to 'which collections is root' info in that case, which
* means test for cycles in collection relationships may fail here. I don't think that is an * means test for cycles in collection relationships may fail here. I don't think that is an
* issue in practice here, but worth keeping in mind... */ * issue in practice here, but worth keeping in mind... */

View File

@ -626,7 +626,8 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc)
} }
/* Restriction flags stay set, so we need to check parents */ /* Restriction flags stay set, so we need to check parents */
CollectionParent *parent = static_cast<CollectionParent *>(lc->collection->parents.first); CollectionParent *parent = static_cast<CollectionParent *>(
lc->collection->runtime.parents.first);
if (parent) { if (parent) {
lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection); lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection);
@ -662,7 +663,8 @@ bool BKE_layer_collection_activate(ViewLayer *view_layer, LayerCollection *lc)
LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, LayerCollection *lc) LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, LayerCollection *lc)
{ {
CollectionParent *parent = static_cast<CollectionParent *>(lc->collection->parents.first); CollectionParent *parent = static_cast<CollectionParent *>(
lc->collection->runtime.parents.first);
if (parent) { if (parent) {
lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection); lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection);

View File

@ -277,7 +277,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
(ID *)scene_src->master_collection, (ID *)scene_src->master_collection,
(ID **)&scene_dst->master_collection, (ID **)&scene_dst->master_collection,
flag_private_id_data); flag_private_id_data);
scene_dst->master_collection->owner_id = &scene_dst->id; scene_dst->master_collection->runtime.owner_id = &scene_dst->id;
} }
/* View Layers */ /* View Layers */

View File

@ -609,7 +609,7 @@ static void template_id_liboverride_hierarchy_collection_root_find_recursive(
*r_collection_parent_best = collection; *r_collection_parent_best = collection;
} }
} }
for (CollectionParent *iter = static_cast<CollectionParent *>(collection->parents.first); for (CollectionParent *iter = static_cast<CollectionParent *>(collection->runtime.parents.first);
iter != nullptr; iter != nullptr;
iter = iter->next) { iter = iter->next) {
if (iter->collection->id.lib != collection->id.lib && ID_IS_LINKED(iter->collection)) { if (iter->collection->id.lib != collection->id.lib && ID_IS_LINKED(iter->collection)) {
@ -628,7 +628,8 @@ static void template_id_liboverride_hierarchy_collections_tag_recursive(
/* Tag all local parents of the root collection, so that usages of the root collection and other /* Tag all local parents of the root collection, so that usages of the root collection and other
* linked ones can be replaced by the local overrides in those parents too. */ * linked ones can be replaced by the local overrides in those parents too. */
if (do_parents) { if (do_parents) {
for (CollectionParent *iter = static_cast<CollectionParent *>(root_collection->parents.first); for (CollectionParent *iter =
static_cast<CollectionParent *>(root_collection->runtime.parents.first);
iter != nullptr; iter != nullptr;
iter = iter->next) { iter = iter->next) {
if (ID_IS_LINKED(iter->collection)) { if (ID_IS_LINKED(iter->collection)) {

View File

@ -2435,7 +2435,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
case ID_GR: { case ID_GR: {
Collection *collection_root = (Collection *)id_root; Collection *collection_root = (Collection *)id_root;
LISTBASE_FOREACH_MUTABLE ( LISTBASE_FOREACH_MUTABLE (
CollectionParent *, collection_parent, &collection_root->parents) { CollectionParent *, collection_parent, &collection_root->runtime.parents) {
if (ID_IS_LINKED(collection_parent->collection) || if (ID_IS_LINKED(collection_parent->collection) ||
!BKE_view_layer_has_collection(view_layer, collection_parent->collection)) { !BKE_view_layer_has_collection(view_layer, collection_parent->collection)) {
continue; continue;

View File

@ -368,7 +368,7 @@ void outliner_collection_delete(
skip = true; skip = true;
} }
else { else {
LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) { LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
Collection *parent = cparent->collection; Collection *parent = cparent->collection;
if (ID_IS_LINKED(parent) || ID_IS_OVERRIDE_LIBRARY(parent)) { if (ID_IS_LINKED(parent) || ID_IS_OVERRIDE_LIBRARY(parent)) {
skip = true; skip = true;

View File

@ -1235,7 +1235,7 @@ static char *collection_drop_tooltip(bContext *C,
/* Test if we are moving within same parent collection. */ /* Test if we are moving within same parent collection. */
bool same_level = false; bool same_level = false;
LISTBASE_FOREACH (CollectionParent *, parent, &data.to->parents) { LISTBASE_FOREACH (CollectionParent *, parent, &data.to->runtime.parents) {
if (data.from == parent->collection) { if (data.from == parent->collection) {
same_level = true; same_level = true;
} }

View File

@ -560,7 +560,7 @@ void outliner_collection_isolate_flag(Scene *scene,
else { else {
CollectionParent *parent; CollectionParent *parent;
Collection *child = collection; Collection *child = collection;
while ((parent = static_cast<CollectionParent *>(child->parents.first))) { while ((parent = static_cast<CollectionParent *>(child->runtime.parents.first))) {
if (parent->collection->flag & COLLECTION_IS_MASTER) { if (parent->collection->flag & COLLECTION_IS_MASTER) {
break; break;
} }

View File

@ -189,7 +189,7 @@ bool TreeDisplayLibraries::library_id_filter_poll(const Library *lib, ID *id) co
Collection *collection = (Collection *)id; Collection *collection = (Collection *)id;
bool has_non_scene_parent = false; bool has_non_scene_parent = false;
for (CollectionParent *cparent : List<CollectionParent>(collection->parents)) { for (CollectionParent *cparent : List<CollectionParent>(collection->runtime.parents)) {
if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) { if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
has_non_scene_parent = true; has_non_scene_parent = true;
} }

View File

@ -44,12 +44,31 @@ enum eCollectionLineArt_Flags {
COLLECTION_LRT_USE_INTERSECTION_PRIORITY = (1 << 1), COLLECTION_LRT_USE_INTERSECTION_PRIORITY = (1 << 1),
}; };
typedef struct Collection_Runtime {
/** The ID owning this collection, in case it is an embedded one. */
ID *owner_id;
/**
* Cache of objects in this collection and all its children.
* This is created on demand when e.g. some physics simulation needs it,
* we don't want to have it for every collections due to memory usage reasons.
*/
ListBase object_cache;
/** Need this for line art sub-collection selections. */
ListBase object_cache_instanced;
/** List of collections that are a parent of this data-block. */
ListBase parents;
uint8_t tag;
char _pad0[7];
} Collection_Runtime;
typedef struct Collection { typedef struct Collection {
ID id; ID id;
/** The ID owning this node tree, in case it is an embedded one. */
ID *owner_id;
/** CollectionObject. */ /** CollectionObject. */
ListBase gobject; ListBase gobject;
/** CollectionChild. */ /** CollectionChild. */
@ -60,56 +79,51 @@ typedef struct Collection {
unsigned int layer DNA_DEPRECATED; unsigned int layer DNA_DEPRECATED;
float instance_offset[3]; float instance_offset[3];
short flag; uint8_t flag;
/* Runtime-only, always cleared on file load. */ int8_t color_tag;
short tag;
short lineart_usage; /* eCollectionLineArt_Usage */ char _pad0[2];
unsigned char lineart_flags; /* eCollectionLineArt_Flags */
unsigned char lineart_intersection_mask;
unsigned char lineart_intersection_priority;
char _pad[5];
int16_t color_tag; uint8_t lineart_usage; /* #eCollectionLineArt_Usage */
uint8_t lineart_flags; /* #eCollectionLineArt_Flags */
uint8_t lineart_intersection_mask;
uint8_t lineart_intersection_priority;
/* Runtime. Cache of objects in this collection and all its
* children. This is created on demand when e.g. some physics
* simulation needs it, we don't want to have it for every
* collections due to memory usage reasons. */
ListBase object_cache;
/* Need this for line art sub-collection selections. */
ListBase object_cache_instanced;
/* Runtime. List of collections that are a parent of this
* datablock. */
ListBase parents;
/* Deprecated */
struct SceneCollection *collection DNA_DEPRECATED; struct SceneCollection *collection DNA_DEPRECATED;
struct ViewLayer *view_layer DNA_DEPRECATED; struct ViewLayer *view_layer DNA_DEPRECATED;
/* Keep last. */
Collection_Runtime runtime;
} Collection; } Collection;
/* Collection->flag */ /** #Collection.flag */
enum { enum {
COLLECTION_HIDE_VIEWPORT = (1 << 0), /* Disable in viewports. */ /** Disable in viewports. */
COLLECTION_HIDE_SELECT = (1 << 1), /* Not selectable in viewport. */ COLLECTION_HIDE_VIEWPORT = (1 << 0),
/* COLLECTION_DISABLED_DEPRECATED = (1 << 2), */ /* Not used anymore */ /** Not selectable in viewport. */
COLLECTION_HIDE_RENDER = (1 << 3), /* Disable in renders. */ COLLECTION_HIDE_SELECT = (1 << 1),
COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */ // COLLECTION_DISABLED_DEPRECATED = (1 << 2), /* DIRTY */
COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */ /** Disable in renders. */
COLLECTION_HAS_OBJECT_CACHE_INSTANCED = (1 << 6), /* for object_cache_instanced. */ COLLECTION_HIDE_RENDER = (1 << 3),
/** Runtime: object_cache is populated. */
COLLECTION_HAS_OBJECT_CACHE = (1 << 4),
/** Is master collection embedded in the scene. */
COLLECTION_IS_MASTER = (1 << 5),
/** for object_cache_instanced. */
COLLECTION_HAS_OBJECT_CACHE_INSTANCED = (1 << 6),
}; };
/* Collection->tag */ /** #Collection_Runtime.tag */
enum { enum {
/* That code (BKE_main_collections_parent_relations_rebuild and the like) /**
* That code (#BKE_main_collections_parent_relations_rebuild and the like)
* is called from very low-level places, like e.g ID remapping... * is called from very low-level places, like e.g ID remapping...
* Using a generic tag like LIB_TAG_DOIT for this is just impossible, we need our very own. */ * Using a generic tag like #LIB_TAG_DOIT for this is just impossible, we need our very own.
*/
COLLECTION_TAG_RELATION_REBUILD = (1 << 0), COLLECTION_TAG_RELATION_REBUILD = (1 << 0),
}; };
/* Collection->color_tag. */ /** #Collection.color_tag */
typedef enum CollectionColorTag { typedef enum CollectionColorTag {
COLLECTION_COLOR_NONE = -1, COLLECTION_COLOR_NONE = -1,
COLLECTION_COLOR_01, COLLECTION_COLOR_01,

View File

@ -31,6 +31,9 @@ const EnumPropertyItem rna_enum_collection_color_items[] = {
{COLLECTION_COLOR_08, "COLOR_08", ICON_COLLECTION_COLOR_08, "Color 08", ""}, {COLLECTION_COLOR_08, "COLOR_08", ICON_COLLECTION_COLOR_08, "Color 08", ""},
{0, NULL, 0, NULL, NULL}, {0, NULL, 0, NULL, NULL},
}; };
/* Minus 1 for NONE & 1 for the NULL sentinel. */
BLI_STATIC_ASSERT(ARRAY_SIZE(rna_enum_collection_color_items) - 2 == COLLECTION_COLOR_TOT,
"Collection color total is an invalid size");
#ifdef RNA_RUNTIME #ifdef RNA_RUNTIME