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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c4
-rw-r--r--source/blender/blenkernel/intern/collection.c1275
-rw-r--r--source/blender/blenkernel/intern/collision.c38
-rw-r--r--source/blender/blenkernel/intern/context.c15
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c18
-rw-r--r--source/blender/blenkernel/intern/effect.c23
-rw-r--r--source/blender/blenkernel/intern/freestyle.c2
-rw-r--r--source/blender/blenkernel/intern/group.c389
-rw-r--r--source/blender/blenkernel/intern/icons.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c2
-rw-r--r--source/blender/blenkernel/intern/layer.c1272
-rw-r--r--source/blender/blenkernel/intern/library.c14
-rw-r--r--source/blender/blenkernel/intern/library_query.c39
-rw-r--r--source/blender/blenkernel/intern/library_remap.c95
-rw-r--r--source/blender/blenkernel/intern/object.c57
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c127
-rw-r--r--source/blender/blenkernel/intern/particle.c18
-rw-r--r--source/blender/blenkernel/intern/pointcache.c5
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c40
-rw-r--r--source/blender/blenkernel/intern/scene.c59
-rw-r--r--source/blender/blenkernel/intern/softbody.c36
21 files changed, 1338 insertions, 2192 deletions
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index b0c571bf159..7b149761952 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -98,7 +98,7 @@ bool BKE_copybuffer_read(Main *bmain_dst, const char *libname, ReportList *repor
/* Here appending/linking starts. */
Main *mainl = BLO_library_link_begin(bmain_dst, &bh, libname);
BLO_library_link_copypaste(mainl, bh);
- BLO_library_link_end(mainl, &bh, 0, NULL, NULL);
+ BLO_library_link_end(mainl, &bh, 0, NULL, NULL, NULL);
/* Mark all library linked objects to be updated. */
BKE_main_lib_objects_recalc_all(bmain_dst);
IMB_colormanagement_check_file_config(bmain_dst);
@@ -145,7 +145,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
BLO_library_link_copypaste(mainl, bh);
- BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
+ BLO_library_link_end(mainl, &bh, flag, bmain, scene, view_layer);
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 4303f7d9150..5ba4a1196b8 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -31,15 +31,17 @@
#include "BLI_iterator.h"
#include "BLI_listbase.h"
#include "BLI_math_base.h"
+#include "BLI_threads.h"
#include "BLT_translation.h"
#include "BLI_string_utils.h"
#include "BKE_collection.h"
-#include "BKE_group.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_object.h"
#include "BKE_scene.h"
#include "DNA_group_types.h"
@@ -48,412 +50,573 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
#include "MEM_guardedalloc.h"
-/* Prototypes. */
-static SceneCollection *find_collection_parent(const struct SceneCollection *sc_child, struct SceneCollection *sc_parent);
-static bool is_collection_in_tree(const struct SceneCollection *sc_reference, struct SceneCollection *sc_parent);
+/******************************** Prototypes ********************************/
-static SceneCollection *collection_master_from_id(const ID *owner_id)
-{
- switch (GS(owner_id->name)) {
- case ID_SCE:
- return ((Scene *)owner_id)->collection;
- case ID_GR:
- return ((Group *)owner_id)->collection;
- default:
- BLI_assert(!"ID doesn't support collections");
- return NULL;
- }
-}
+static bool collection_child_add(Collection *parent, Collection *collection, int flag, const bool add_us);
+static bool collection_child_remove(Collection *parent, Collection *collection);
+static bool collection_object_add(Collection *collection, Object *ob, int flag, const bool add_us);
+static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us);
-/**
- * The automatic/fallback name of a new collection.
- */
-void BKE_collection_new_name_get(ID *owner_id, SceneCollection *sc_parent, char *rname)
-{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
- char *name;
+static CollectionChild *collection_find_child(Collection *parent, Collection *collection);
+static CollectionParent *collection_find_parent(Collection *child, Collection *collection);
- if (sc_parent == sc_master) {
- name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
- }
- else {
- const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1;
- const int digits = integer_digits_i(number);
- const int max_len = sizeof(sc_parent->name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */;
- name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number);
- }
+static bool collection_find_child_recursive(Collection *parent, Collection *collection);
- BLI_strncpy(rname, name, MAX_NAME);
- MEM_freeN(name);
-}
+/***************************** Add Collection *******************************/
-/**
- * Add a new collection, but don't handle syncing with layer collections
- */
-static SceneCollection *collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+/* Add new collection, without view layer syncing. */
+static Collection *collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
- SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
- sc->type = type;
+ /* Determine new collection name. */
char name[MAX_NAME];
- if (!sc_parent) {
- sc_parent = sc_master;
- }
-
- if (name_custom != NULL) {
- BLI_strncpy(name, name_custom, MAX_NAME);
+ if (name_custom) {
+ STRNCPY(name, name_custom);
}
else {
- BKE_collection_new_name_get(owner_id, sc_parent, name);
+ BKE_collection_new_name_get(collection_parent, name);
}
- BLI_addtail(&sc_parent->scene_collections, sc);
- BKE_collection_rename(owner_id, sc, name);
+ /* Create new collection. */
+ Collection *collection = BKE_libblock_alloc(bmain, ID_GR, name, 0);
+
+ /* We increase collection user count when linking to Collections. */
+ id_us_min(&collection->id);
+
+ /* Optionally add to parent collection. */
+ if (collection_parent) {
+ collection_child_add(collection_parent, collection, 0, true);
+ }
- return sc;
+ return collection;
}
/**
* Add a collection to a collection ListBase and syncronize all render layers
* The ListBase is NULL when the collection is to be added to the master collection
*/
-SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
{
- if (sc_parent == NULL) {
- sc_parent = BKE_collection_master(owner_id);
- }
+ Collection *collection = collection_add(bmain, collection_parent, name_custom);
+ BKE_main_collection_sync(bmain);
+ return collection;
+}
- SceneCollection *scene_collection = collection_add(owner_id, sc_parent, type, name_custom);
- BKE_layer_sync_new_scene_collection(owner_id, sc_parent, scene_collection);
- return scene_collection;
+/*********************** Free and Delete Collection ****************************/
+
+/** 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_previewimg_free(&collection->preview);
+
+ BLI_freelistN(&collection->gobject);
+ BLI_freelistN(&collection->children);
+ BLI_freelistN(&collection->parents);
+
+ BKE_collection_object_cache_free(collection);
}
/**
- * Free the collection items recursively
+ * Remove a collection, optionally removing its child objects or moving
+ * them to parent collections.
*/
-static void collection_free(SceneCollection *sc, const bool do_id_user)
+bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
{
- if (do_id_user) {
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- id_us_min(link->data);
+ /* Master collection is not real datablock, can't be removed. */
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BLI_assert("!Scene master collection can't be deleted");
+ return false;
+ }
+
+ if (hierarchy) {
+ /* Remove child objects. */
+ CollectionObject *cob = collection->gobject.first;
+ while (cob != NULL) {
+ collection_object_remove(bmain, collection, cob->ob, true);
+ cob = collection->gobject.first;
+ }
+
+ /* Delete all child collections recursively. */
+ CollectionChild *child = collection->children.first;
+ while (child != NULL) {
+ BKE_collection_delete(bmain, child->collection, hierarchy);
+ child = collection->children.first;
}
}
+ else {
+ /* Link child collections into parent collection. */
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ Collection *parent = cparent->collection;
+ collection_child_add(parent, child->collection, 0, true);
+ }
+ }
- BLI_freelistN(&sc->objects);
+ CollectionObject *cob = collection->gobject.first;
+ while (cob != NULL) {
+ /* Link child object into parent collections. */
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ Collection *parent = cparent->collection;
+ collection_object_add(parent, cob->ob, 0, true);
+ }
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- collection_free(nsc, do_id_user);
+ /* Remove child object. */
+ collection_object_remove(bmain, collection, cob->ob, true);
+ cob = collection->gobject.first;
+ }
}
- BLI_freelistN(&sc->scene_collections);
+
+ BKE_libblock_delete(bmain, collection);
+
+ BKE_main_collection_sync(bmain);
+
+ return true;
}
+/***************************** Collection Copy *******************************/
+
/**
- * Unlink the collection recursively
- * \return true if unlinked.
+ * Only copy internal data of Collection ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
+void BKE_collection_copy_data(Main *UNUSED(bmain), Collection *collection_dst, const Collection *collection_src, const int flag)
{
- for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) {
- if (sc == sc_gone) {
- BLI_remlink(&sc_parent->scene_collections, sc_gone);
- return true;
- }
+ /* Do not copy collection's preview (same behavior as for objects). */
+ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
+ BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id);
+ }
+ else {
+ collection_dst->preview = NULL;
+ }
- if (collection_remlink(sc, sc_gone)) {
- return true;
- }
+ collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ BLI_listbase_clear(&collection_dst->object_cache);
+
+ BLI_listbase_clear(&collection_dst->gobject);
+ BLI_listbase_clear(&collection_dst->children);
+ BLI_listbase_clear(&collection_dst->parents);
+
+ for (CollectionChild *child = collection_src->children.first; child; child = child->next) {
+ collection_child_add(collection_dst, child->collection, flag, false);
+ }
+ for (CollectionObject *cob = collection_src->gobject.first; cob; cob = cob->next) {
+ collection_object_add(collection_dst, cob->ob, flag, false);
}
- return false;
}
/**
- * Recursively remove any instance of this SceneCollection
+ * Makes a shallow copy of a Collection
+ *
+ * Add a new collection in the same level as the old one, copy any nested collections
+ * but link the objects to the new collection (as oppose to copy them).
*/
-static void layer_collection_remove(ViewLayer *view_layer, ListBase *lb, const SceneCollection *sc)
-{
- LayerCollection *lc = lb->first;
- while (lc) {
- if (lc->scene_collection == sc) {
- BKE_layer_collection_free(view_layer, lc);
- BLI_remlink(lb, lc);
-
- LayerCollection *lc_next = lc->next;
- MEM_freeN(lc);
- lc = lc_next;
-
- /* only the "top-level" layer collections may have the
- * same SceneCollection in a sibling tree.
- */
- if (lb != &view_layer->layer_collections) {
- return;
- }
- }
+Collection *BKE_collection_copy(Main *bmain, Collection *parent, Collection *collection)
+{
+ /* It's not allowed to copy the master collection. */
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ BLI_assert("!Master collection can't be copied");
+ return NULL;
+ }
- else {
- layer_collection_remove(view_layer, &lc->layer_collections, sc);
- lc = lc->next;
+ Collection *collection_new;
+ BKE_id_copy_ex(bmain, &collection->id, (ID **)&collection_new, 0, false);
+
+ /* Optionally add to parent. */
+ if (parent) {
+ if (collection_child_add(parent, collection_new, 0, true)) {
+ /* Put collection right after existing one. */
+ CollectionChild *child = collection_find_child(parent, collection);
+ CollectionChild *child_new = collection_find_child(parent, collection_new);
+
+ if (child && child_new) {
+ BLI_remlink(&parent->children, child_new);
+ BLI_insertlinkafter(&parent->children, child, child_new);
+ }
}
}
+
+ BKE_main_collection_sync(bmain);
+
+ return collection_new;
}
+Collection *BKE_collection_copy_master(Main *bmain, Collection *collection, const int flag)
+{
+ BLI_assert(collection->flag & COLLECTION_IS_MASTER);
+
+ Collection *collection_dst = MEM_dupallocN(collection);
+ BKE_collection_copy_data(bmain, collection_dst, collection, flag);
+ return collection_dst;
+}
+
+void BKE_collection_copy_full(Main *UNUSED(bmain), Collection *UNUSED(collection))
+{
+ // TODO: implement full scene copy
+}
+
+void BKE_collection_make_local(Main *bmain, Collection *collection, const bool lib_local)
+{
+ BKE_id_make_local_generic(bmain, &collection->id, true, lib_local);
+}
+
+/********************************* Naming *******************************/
+
/**
- * Remove a collection from the scene, and syncronize all render layers
- *
- * If an object is in any other collection, link the object to the master collection.
+ * The automatic/fallback name of a new collection.
*/
-bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
+void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
{
- SceneCollection *sc_master = collection_master_from_id(owner_id);
+ char *name;
- /* The master collection cannot be removed. */
- if (sc == sc_master) {
- return false;
+ if (!collection_parent) {
+ name = BLI_sprintfN("Collection");
}
-
- /* We need to do bottom up removal, otherwise we get a crash when we remove a collection that
- * has one of its nested collections linked to a view layer. */
- SceneCollection *scene_collection_nested = sc->scene_collections.first;
- while (scene_collection_nested != NULL) {
- SceneCollection *scene_collection_next = scene_collection_nested->next;
- BKE_collection_remove(owner_id, scene_collection_nested);
- scene_collection_nested = scene_collection_next;
+ else if (collection_parent->flag & COLLECTION_IS_MASTER) {
+ name = BLI_sprintfN("Collection %d", BLI_listbase_count(&collection_parent->children) + 1);
}
-
- /* Unlink from the respective collection tree. */
- if (!collection_remlink(sc_master, sc)) {
- BLI_assert(false);
+ else {
+ const int number = BLI_listbase_count(&collection_parent->children) + 1;
+ const int digits = integer_digits_i(number);
+ const int max_len = sizeof(collection_parent->id.name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */ - 2 /* ID */;
+ name = BLI_sprintfN("%.*s %d", max_len, collection_parent->id.name + 2, number);
}
- /* If an object is no longer in any collection, we add it to the master collection. */
- ListBase collection_objects;
- BLI_duplicatelist(&collection_objects, &sc->objects);
+ BLI_strncpy(rname, name, MAX_NAME);
+ MEM_freeN(name);
+}
- FOREACH_SCENE_COLLECTION_BEGIN(owner_id, scene_collection_iter)
+/************************* Dependencies ****************************/
+
+bool BKE_collection_is_animated(Collection *collection, Object *UNUSED(parent))
+{
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
- if (scene_collection_iter == sc) {
- continue;
+ if (object->proxy) {
+ return true;
}
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ return false;
+}
- LinkData *link_next, *link = collection_objects.first;
- while (link) {
- link_next = link->next;
+/* puts all collection members in local timing system, after this call
+ * you can draw everything, leaves tags in objects to signal it needs further updating */
- if (BLI_findptr(&scene_collection_iter->objects, link->data, offsetof(LinkData, data))) {
- BLI_remlink(&collection_objects, link);
- MEM_freeN(link);
- }
-
- link = link_next;
+/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
+void BKE_collection_handle_recalc_and_update(struct Depsgraph *depsgraph, Scene *scene, Object *UNUSED(parent), Collection *collection)
+{
+ /* only do existing tags, as set by regular depsgraph */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
+ {
+ if (object->id.recalc & ID_RECALC_ALL) {
+ BKE_object_handle_update(depsgraph, scene, object);
}
}
- FOREACH_SCENE_COLLECTION_END;
-
- for (LinkData *link = collection_objects.first; link; link = link->next) {
- BKE_collection_object_add(owner_id, sc_master, link->data);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
- BLI_freelistN(&collection_objects);
+/* **************** Object List Cache *******************/
+
+static void collection_object_cache_fill(ListBase *lb, Collection *collection, int parent_restrict)
+{
+ int child_restrict = collection->flag | parent_restrict;
+
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BLI_findptr(lb, cob->ob, offsetof(Base, object));
+
+ if (base == NULL) {
+ base = MEM_callocN(sizeof(Base), "Object Base");
+ base->object = cob->ob;
- /* Clear the collection items. */
- collection_free(sc, true);
+ if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) {
+ base->flag |= BASE_VISIBLED | BASE_VISIBLE_VIEWPORT;
- /* check all layers that use this collection and clear them */
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- layer_collection_remove(view_layer, &view_layer->layer_collections, sc);
- view_layer->active_collection = 0;
+ if ((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+
+ if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
+ base->flag |= BASE_VISIBLE_RENDER;
+ }
+
+ BLI_addtail(lb, base);
+ }
}
- MEM_freeN(sc);
- return true;
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ collection_object_cache_fill(lb, child->collection, child_restrict);
+ }
}
-/**
- * Copy SceneCollection tree but keep pointing to the same objects
- *
- * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
- */
-void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src, const int flag)
+ListBase BKE_collection_object_cache_get(Collection *collection)
{
- BLI_duplicatelist(&sc_dst->objects, &sc_src->objects);
- if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
- for (LinkData *link = sc_dst->objects.first; link; link = link->next) {
- id_us_plus(link->data);
+ if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
+ static ThreadMutex cache_lock = BLI_MUTEX_INITIALIZER;
+
+ if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
+ BLI_mutex_lock(&cache_lock);
+ collection_object_cache_fill(&collection->object_cache, collection, 0);
+ collection->flag |= COLLECTION_HAS_OBJECT_CACHE;
+ BLI_mutex_unlock(&cache_lock);
}
}
- BLI_duplicatelist(&sc_dst->scene_collections, &sc_src->scene_collections);
- for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first;
- nsc_src;
- nsc_src = nsc_src->next, nsc_dst = nsc_dst->next)
- {
- BKE_collection_copy_data(nsc_dst, nsc_src, flag);
- }
+ return collection->object_cache;
}
-/**
- * Makes a shallow copy of a SceneCollection
- *
- * Add a new collection in the same level as the old one, copy any nested collections
- * but link the objects to the new collection (as oppose to copy them).
- */
-SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection *scene_collection)
+static void collection_object_cache_free(Collection *collection)
{
- SceneCollection *scene_collection_master = BKE_collection_master(owner_id);
- SceneCollection *scene_collection_parent = find_collection_parent(scene_collection, scene_collection_master);
+ /* Clear own cache an for all parents, since those are affected by changes as well. */
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ BLI_freelistN(&collection->object_cache);
- /* It's not allowed to copy the master collection. */
- if (scene_collection_master == scene_collection) {
- return NULL;
+ for (CollectionParent *parent = collection->parents.first; parent; parent = parent->next) {
+ collection_object_cache_free(parent->collection);
}
+}
+
+void BKE_collection_object_cache_free(Collection *collection)
+{
+ collection_object_cache_free(collection);
+}
+
+Base *BKE_collection_or_layer_objects(Depsgraph *depsgraph,
+ const Scene *scene,
+ const ViewLayer *view_layer,
+ Collection *collection)
+{
+ // TODO: this is used by physics to get objects from a collection, but the
+ // the physics systems are not all using the depsgraph correctly which means
+ // we try different things. Instead we should explicitly get evaluated or
+ // non-evaluated data and always have the depsgraph available when needed
- SceneCollection *scene_collection_new = collection_add(
- owner_id,
- scene_collection_parent,
- scene_collection->type,
- scene_collection->name);
+ if (collection) {
+ return BKE_collection_object_cache_get(collection).first;
+ }
+ else if (depsgraph) {
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
- if (scene_collection_new != scene_collection->next) {
- BLI_remlink(&scene_collection_parent->scene_collections, scene_collection_new);
- BLI_insertlinkafter(&scene_collection_parent->scene_collections, scene_collection, scene_collection_new);
+ if (view_layer) {
+ return FIRSTBASE(view_layer);
+ }
+ else {
+ view_layer = DEG_get_input_view_layer(depsgraph);
+ return FIRSTBASE(view_layer);
+ }
+ }
+ else if (view_layer) {
+ return FIRSTBASE(view_layer);
+ }
+ else {
+ /* depsgraph is NULL during deg build */
+ return FIRSTBASE(BKE_view_layer_context_active_PLACEHOLDER(scene));
}
+}
- BKE_collection_copy_data(scene_collection_new, scene_collection, 0);
- BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, scene_collection_new);
+/*********************** Scene Master Collection ***************/
- /* Make sure every linked instance of the new collection has the same values (flags, overrides, ...) as the
- * corresponding original collection. */
- BKE_layer_collection_sync_flags(owner_id, scene_collection_new, scene_collection);
+Collection *BKE_collection_master_add()
+{
+ /* Not an actual datablock, but owned by scene. */
+ Collection *master_collection = MEM_callocN(sizeof(Collection), "Master Collection");
+ STRNCPY(master_collection->id.name, "GRMaster Collection");
+ master_collection->flag |= COLLECTION_IS_MASTER;
+ return master_collection;
+}
- return scene_collection_new;
+Collection *BKE_collection_master(const Scene *scene)
+{
+ return scene->master_collection;
}
-static SceneCollection *master_collection_from_id(const ID *owner_id)
+/*********************** Cyclic Checks ************************/
+
+static bool collection_object_cyclic_check_internal(Object *object, Collection *collection)
{
- switch (GS(owner_id->name)) {
- case ID_SCE:
- return ((const Scene *)owner_id)->collection;
- case ID_GR:
- return ((const Group *)owner_id)->collection;
- default:
- BLI_assert(!"ID doesn't support scene collection");
- return NULL;
+ if (object->dup_group) {
+ Collection *dup_collection = object->dup_group;
+ if ((dup_collection->id.tag & LIB_TAG_DOIT) == 0) {
+ /* Cycle already exists in collections, let's prevent further crappyness */
+ return true;
+ }
+ /* flag the object to identify cyclic dependencies in further dupli collections */
+ dup_collection->id.tag &= ~LIB_TAG_DOIT;
+
+ if (dup_collection == collection) {
+ return true;
+ }
+ else {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(dup_collection, collection_object)
+ {
+ if (collection_object_cyclic_check_internal(collection_object, dup_collection)) {
+ return true;
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+
+ /* un-flag the object, it's allowed to have the same collection multiple times in parallel */
+ dup_collection->id.tag |= LIB_TAG_DOIT;
}
+
+ return false;
}
-/**
- * Returns the master collection of the scene or group
- */
-SceneCollection *BKE_collection_master(const ID *owner_id)
+bool BKE_collection_object_cyclic_check(Main *bmain, Object *object, Collection *collection)
{
- return master_collection_from_id(owner_id);
+ /* first flag all collections */
+ BKE_main_id_tag_listbase(&bmain->collection, LIB_TAG_DOIT, true);
+
+ return collection_object_cyclic_check_internal(object, collection);
}
-static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
+/******************* Collection Object Membership *******************/
+
+bool BKE_collection_has_object(Collection *collection, Object *ob)
{
- SceneCollection *sc_parent = find_collection_parent(sc, collection_master_from_id(owner_id));
- BLI_strncpy(sc->name, name, sizeof(sc->name));
- BLI_uniquename(&sc_parent->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+ if (ELEM(NULL, collection, ob)) {
+ return false;
+ }
+
+ return (BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob)));
}
-void BKE_collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
+bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
{
- collection_rename(owner_id, sc, name);
+ if (ELEM(NULL, collection, ob)) {
+ return false;
+ }
+
+ const ListBase objects = BKE_collection_object_cache_get(collection);
+ return (BLI_findptr(&objects, ob, offsetof(Base, object)));
}
-/**
- * Make sure the collection name is still unique within its siblings.
- */
-static void collection_name_check(const ID *owner_id, SceneCollection *sc)
+Collection *BKE_collection_object_find(Main *bmain, Collection *collection, Object *ob)
{
- /* It's a bit of a hack, we simply try to make sure the collection name is valid. */
- collection_rename(owner_id, sc, sc->name);
+ if (collection)
+ collection = collection->id.next;
+ else
+ collection = bmain->collection.first;
+
+ while (collection) {
+ if (BKE_collection_has_object(collection, ob))
+ return collection;
+ collection = collection->id.next;
+ }
+ return NULL;
}
-/**
- * Free (or release) any data used by the master collection (does not free the master collection itself).
- * Used only to clear the entire scene or group data since it's not doing re-syncing of the LayerCollection tree
- */
-void BKE_collection_master_free(ID *owner_id, const bool do_id_user)
+/********************** Collection Objects *********************/
+
+static bool collection_object_add(Collection *collection, Object *ob, int flag, const bool add_us)
{
- collection_free(BKE_collection_master(owner_id), do_id_user);
+ if (ob->dup_group) {
+ /* Cyclic dependency check. */
+ if (collection_find_child_recursive(collection, ob->dup_group)) {
+ return false;
+ }
+ }
+
+ CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
+ if (cob) {
+ return false;
+ }
+
+ cob = MEM_callocN(sizeof(CollectionObject), __func__);
+ cob->ob = ob;
+ BLI_addtail(&collection->gobject, cob);
+ BKE_collection_object_cache_free(collection);
+
+ if (add_us && (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ id_us_plus(&ob->id);
+ }
+
+ return true;
}
-static void collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
{
- BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+ CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
+ if (cob == NULL) {
+ return false;
+ }
+
+ BLI_freelinkN(&collection->gobject, cob);
+ BKE_collection_object_cache_free(collection);
- if (GS(owner_id->name) == ID_SCE) {
- id_us_plus((ID *)ob);
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
}
else {
- BLI_assert(GS(owner_id->name) == ID_GR);
- if ((ob->flag & OB_FROMGROUP) == 0) {
- ob->flag |= OB_FROMGROUP;
- }
+ id_us_min(&ob->id);
}
- BKE_layer_sync_object_link(owner_id, sc, ob);
+ return true;
}
/**
* Add object to collection
*/
-bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
{
- if (BKE_collection_object_exists(sc, ob)) {
- /* don't add the same object twice */
+ if (ELEM(NULL, collection, ob)) {
return false;
}
- collection_object_add(owner_id, sc, ob);
+ if (!collection_object_add(collection, ob, 0, true)) {
+ return false;
+ }
+
+ if (BKE_collection_is_in_scene(collection)) {
+ BKE_main_collection_sync(bmain);
+ }
+
return true;
}
/**
- * Add object to all collections that reference objects is in
+ * Add object to all scene collections that reference objects is in
* (used to copy objects)
*/
-void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
+void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
{
- FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
{
- if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
- collection_object_add(&scene->id, sc, ob_dst);
+ if (BKE_collection_has_object(collection, ob_src)) {
+ collection_object_add(collection, ob_dst, 0, true);
}
}
FOREACH_SCENE_COLLECTION_END;
+
+ BKE_main_collection_sync(bmain);
}
/**
* Remove object from collection.
- * \param bmain: Can be NULL if free_us is false.
*/
-bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc, Object *ob, const bool free_us)
+bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
{
- LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
-
- if (link == NULL) {
+ if (ELEM(NULL, collection, ob)) {
return false;
}
- BLI_remlink(&sc->objects, link);
- MEM_freeN(link);
-
- BKE_layer_sync_object_unlink(owner_id, sc, ob);
-
- if (GS(owner_id->name) == ID_SCE) {
- if (free_us) {
- BKE_libblock_free_us(bmain, ob);
- }
- else {
- id_us_min(&ob->id);
- }
+ if (collection_object_remove(bmain, collection, ob, free_us)) {
+ return false;
}
- else {
- BLI_assert(GS(owner_id->name) == ID_GR);
+
+ if (BKE_collection_is_in_scene(collection)) {
+ BKE_main_collection_sync(bmain);
}
return true;
@@ -463,408 +626,436 @@ bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc
* Remove object from all collections of scene
* \param scene_collection_skip: Don't remove base from this collection.
*/
-static bool collections_object_remove_ex(Main *bmain, ID *owner_id, Object *ob, const bool free_us,
- SceneCollection *scene_collection_skip)
+static bool scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us,
+ Collection *collection_skip)
{
bool removed = false;
- if (GS(owner_id->name) == ID_SCE) {
- BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob);
- }
- else {
- BLI_assert(GS(owner_id->name) == ID_GR);
- }
- FOREACH_SCENE_COLLECTION_BEGIN(owner_id, sc)
+ BKE_scene_remove_rigidbody_object(scene, ob);
+
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
{
- if (sc != scene_collection_skip) {
- removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ if (collection != collection_skip) {
+ removed |= collection_object_remove(bmain, collection, ob, free_us);
}
}
FOREACH_SCENE_COLLECTION_END;
+
+ BKE_main_collection_sync(bmain);
+
return removed;
}
/**
* Remove object from all collections of scene
*/
-bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us)
+bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
- return collections_object_remove_ex(bmain, owner_id, ob, free_us, NULL);
+ return scene_collections_object_remove(bmain, scene, ob, free_us, NULL);
}
-/**
- * Move object from a collection into another
- *
- * If source collection is NULL move it from all the existing collections.
+/*
+ * Remove all NULL objects from non-scene collections.
+ * This is used for library remapping, where these pointers have been set to NULL.
+ * Otherwise this should never happen.
*/
-void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+void BKE_collections_object_remove_nulls(Main *bmain)
{
- /* In both cases we first add the object, then remove it from the other collections.
- * Otherwise we lose the original base and whether it was active and selected. */
- if (sc_src != NULL) {
- if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
- BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (!BKE_collection_is_in_scene(collection)) {
+ bool changed = false;
+
+ for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) {
+ cob_next = cob->next;
+
+ if (cob->ob == NULL) {
+ BLI_freelinkN(&collection->gobject, cob);
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ BKE_collection_object_cache_free(collection);
+ }
}
}
- else {
- /* Adding will fail if object is already in collection.
- * However we still need to remove it from the other collections. */
- BKE_collection_object_add(owner_id, sc_dst, ob);
- collections_object_remove_ex(NULL, owner_id, ob, false, sc_dst);
- }
}
-/**
- * Whether the object is directly inside the collection.
+/*
+ * Remove all NULL children from parent objects of changed old_collection.
+ * This is used for library remapping, where these pointers have been set to NULL.
+ * Otherwise this should never happen.
*/
-bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob)
+void BKE_collections_child_remove_nulls(Main *bmain, Collection *old_collection)
{
- if (BLI_findptr(&scene_collection->objects, ob, offsetof(LinkData, data))) {
- return true;
- }
- return false;
-}
+ bool changed = false;
-static SceneCollection *scene_collection_from_index_recursive(SceneCollection *scene_collection, const int index, int *index_current)
-{
- if (index == (*index_current)) {
- return scene_collection;
+ for (CollectionChild *child = old_collection->children.first; child; child = child->next) {
+ CollectionParent *cparent = collection_find_parent(child->collection, old_collection);
+ if (cparent) {
+ BLI_freelinkN(&child->collection->parents, cparent);
+ }
}
- (*index_current)++;
+ for (CollectionParent *cparent = old_collection->parents.first; cparent; cparent = cparent->next) {
+ Collection *parent = cparent->collection;
- for (SceneCollection *scene_collection_iter = scene_collection->scene_collections.first;
- scene_collection_iter != NULL;
- scene_collection_iter = scene_collection_iter->next)
- {
- SceneCollection *nested = scene_collection_from_index_recursive(scene_collection_iter, index, index_current);
- if (nested != NULL) {
- return nested;
+ for (CollectionChild *child = parent->children.first, *child_next = NULL; child; child = child_next) {
+ child_next = child->next;
+
+ if (child->collection == NULL) {
+ BLI_freelinkN(&parent->children, child);
+ changed = true;
+ }
}
}
- return NULL;
-}
-/**
- * Return Scene Collection for a given index.
- *
- * The index is calculated from top to bottom counting the children before the siblings.
- */
-SceneCollection *BKE_collection_from_index(Scene *scene, const int index)
-{
- int index_current = 0;
- SceneCollection *master_collection = BKE_collection_master(&scene->id);
- return scene_collection_from_index_recursive(master_collection, index, &index_current);
-}
+ BLI_freelistN(&old_collection->parents);
-static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
-{
- lc_dst->flag = lc_src->flag;
-
- /* Continue recursively. */
- LayerCollection *lc_dst_nested, *lc_src_nested;
- lc_src_nested = lc_src->layer_collections.first;
- for (lc_dst_nested = lc_dst->layer_collections.first;
- lc_dst_nested && lc_src_nested;
- lc_dst_nested = lc_dst_nested->next, lc_src_nested = lc_src_nested->next)
- {
- layer_collection_sync(lc_dst_nested, lc_src_nested);
+ if (changed) {
+ BKE_main_collection_sync(bmain);
}
}
/**
- * Select all the objects in this SceneCollection (and its nested collections) for this ViewLayer.
- * Return true if any object was selected.
+ * Move object from a collection into another
+ *
+ * If source collection is NULL move it from all the existing collections.
*/
-bool BKE_collection_objects_select(ViewLayer *view_layer, SceneCollection *scene_collection)
+void BKE_collection_object_move(Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
{
- LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection);
- if (layer_collection != NULL) {
- BKE_layer_collection_objects_select(layer_collection);
- return true;
+ /* In both cases we first add the object, then remove it from the other collections.
+ * Otherwise we lose the original base and whether it was active and selected. */
+ if (collection_src != NULL) {
+ if (BKE_collection_object_add(bmain, collection_dst, ob)) {
+ BKE_collection_object_remove(bmain, collection_src, ob, false);
+ }
}
else {
- /* Slower approach, we need to iterate over all the objects and for each one we see if there is a base. */
- bool changed = false;
- for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
- Base *base = BKE_view_layer_base_find(view_layer, link->data);
- if (base != NULL) {
- if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
- base->flag |= BASE_SELECTED;
- changed = true;
- }
- }
- }
- return changed;
+ /* Adding will fail if object is already in collection.
+ * However we still need to remove it from the other collections. */
+ BKE_collection_object_add(bmain, collection_dst, ob);
+ scene_collections_object_remove(bmain, scene, ob, false, collection_dst);
}
}
-/**
- * Leave only the master collection in, remove everything else.
- * @param group
- */
-static void collection_group_cleanup(Group *group)
+/***************** Collection Scene Membership ****************/
+
+bool BKE_collection_is_in_scene(Collection *collection)
{
- /* Unlink all the LayerCollections. */
- while (group->view_layer->layer_collections.last != NULL) {
- BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.last);
+ if (collection->flag & COLLECTION_IS_MASTER) {
+ return true;
+ }
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (BKE_collection_is_in_scene(cparent->collection)) {
+ return true;
+ }
}
- /* Remove all the SceneCollections but the master. */
- collection_free(group->collection, false);
+ return false;
}
-/**
- * Create a group from a collection
- *
- * Any ViewLayer that may have this the related SceneCollection linked is converted
- * to a Group Collection.
- */
-Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *lc_src)
+void BKE_collections_after_lib_link(Main *bmain)
{
- SceneCollection *sc_dst, *sc_src = lc_src->scene_collection;
- LayerCollection *lc_dst;
+ /* Update view layer collections to match any changes in linked
+ * collections after file load. */
+ BKE_main_collection_sync(bmain);
+}
- /* The master collection can't be converted. */
- if (sc_src == BKE_collection_master(&scene->id)) {
- return NULL;
- }
+/********************** Collection Children *******************/
- /* If a sub-collection of sc_dst is directly linked into a ViewLayer we can't convert. */
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- for (LayerCollection *lc_child = view_layer->layer_collections.first; lc_child; lc_child = lc_child->next) {
- if (is_collection_in_tree(lc_child->scene_collection, sc_src)) {
- return NULL;
- }
- }
+bool BKE_collection_find_cycle(Collection *new_ancestor, Collection *collection)
+{
+ if (collection == new_ancestor) {
+ return true;
}
- /* Create new group with the same data as the original collection. */
- Group *group = BKE_group_add(bmain, sc_src->name);
- collection_group_cleanup(group);
-
- sc_dst = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name);
- BKE_collection_copy_data(sc_dst, sc_src, 0);
- FOREACH_SCENE_COLLECTION_BEGIN(&group->id, sc_group)
- {
- sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
+ for (CollectionParent *parent = new_ancestor->parents.first; parent; parent = parent->next) {
+ if (BKE_collection_find_cycle(parent->collection, collection)) {
+ return true;
+ }
}
- FOREACH_SCENE_COLLECTION_END;
- lc_dst = BKE_collection_link(group->view_layer, sc_dst);
- layer_collection_sync(lc_dst, lc_src);
-
- return group;
+ return false;
}
-/* ---------------------------------------------------------------------- */
-/* Outliner drag and drop */
+static CollectionChild *collection_find_child(Collection *parent, Collection *collection)
+{
+ return BLI_findptr(&parent->children, collection, offsetof(CollectionChild, collection));
+}
-/**
- * Find and return the SceneCollection that has \a sc_child as one of its directly
- * nested SceneCollection.
- *
- * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection
- */
-static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent)
+static bool collection_find_child_recursive(Collection *parent, Collection *collection)
{
- for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
- if (sc_nested == sc_child) {
- return sc_parent;
+ for (CollectionChild *child = parent->children.first; child; child = child->next) {
+ if (child->collection == collection) {
+ return true;
}
- SceneCollection *found = find_collection_parent(sc_child, sc_nested);
- if (found) {
- return found;
+ if (collection_find_child_recursive(child->collection, collection)) {
+ return true;
}
}
- return NULL;
+ return false;
}
-/**
- * Check if \a sc_reference is nested to \a sc_parent SceneCollection
- */
-static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent)
+static CollectionParent *collection_find_parent(Collection *child, Collection *collection)
{
- return find_collection_parent(sc_reference, sc_parent) != NULL;
+ return BLI_findptr(&child->parents, collection, offsetof(CollectionParent, collection));
}
-bool BKE_collection_move_above(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+static bool collection_child_add(Collection *parent, Collection *collection, const int flag, const bool add_us)
{
- /* Find the SceneCollection the sc_src belongs to */
- SceneCollection *sc_master = master_collection_from_id(owner_id);
-
- /* Master Layer can't be moved around*/
- if (ELEM(sc_master, sc_src, sc_dst)) {
+ CollectionChild *child = collection_find_child(parent, collection);
+ if (child) {
return false;
}
-
- /* collection is already where we wanted it to be */
- if (sc_dst->prev == sc_src) {
+ if (BKE_collection_find_cycle(parent, collection)) {
return false;
}
- /* We can't move a collection fs the destiny collection
- * is nested to the source collection */
- if (is_collection_in_tree(sc_dst, sc_src)) {
- return false;
+ child = MEM_callocN(sizeof(CollectionChild), "CollectionChild");
+ child->collection = collection;
+ BLI_addtail(&parent->children, child);
+
+ /* Don't add parent links for depsgraph datablocks, these are not kept in sync. */
+ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
+ cparent->collection = parent;
+ BLI_addtail(&collection->parents, cparent);
}
- SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
- SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
- BLI_assert(sc_src_parent);
- BLI_assert(sc_dst_parent);
+ if (add_us) {
+ id_us_plus(&collection->id);
+ }
- /* Remove sc_src from its parent */
- BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+ BKE_collection_object_cache_free(parent);
- /* Re-insert it where it belongs */
- BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+ return true;
+}
+
+static bool collection_child_remove(Collection *parent, Collection *collection)
+{
+ CollectionChild *child = collection_find_child(parent, collection);
+ if (child == NULL) {
+ return false;
+ }
- /* Update the tree */
- BKE_layer_collection_resync(owner_id, sc_src_parent);
- BKE_layer_collection_resync(owner_id, sc_dst_parent);
+ CollectionParent *cparent = collection_find_parent(collection, parent);
+ BLI_freelinkN(&collection->parents, cparent);
+ BLI_freelinkN(&parent->children, child);
- /* Keep names unique. */
- collection_name_check(owner_id, sc_src);
+ id_us_min(&collection->id);
+
+ BKE_collection_object_cache_free(parent);
return true;
}
-bool BKE_collection_move_below(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+bool BKE_collection_child_add(Main *bmain, Collection *parent, Collection *child)
{
- /* Find the SceneCollection the sc_src belongs to */
- SceneCollection *sc_master = master_collection_from_id(owner_id);
-
- /* Master Layer can't be moved around*/
- if (ELEM(sc_master, sc_src, sc_dst)) {
+ if (!collection_child_add(parent, child, 0, true)) {
return false;
}
- /* Collection is already where we wanted it to be */
- if (sc_dst->next == sc_src) {
- return false;
- }
+ BKE_main_collection_sync(bmain);
+ return true;
+}
- /* We can't move a collection if the destiny collection
- * is nested to the source collection */
- if (is_collection_in_tree(sc_dst, sc_src)) {
+bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
+{
+ if (!collection_child_remove(parent, child)) {
return false;
}
- SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
- SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
- BLI_assert(sc_src_parent);
- BLI_assert(sc_dst_parent);
+ BKE_main_collection_sync(bmain);
+ return true;
+}
- /* Remove sc_src from its parent */
- BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+/********************** Collection index *********************/
- /* Re-insert it where it belongs */
- BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+static Collection *collection_from_index_recursive(Collection *collection, const int index, int *index_current)
+{
+ if (index == (*index_current)) {
+ return collection;
+ }
- /* Update the tree */
- BKE_layer_collection_resync(owner_id, sc_src_parent);
- BKE_layer_collection_resync(owner_id, sc_dst_parent);
+ (*index_current)++;
- /* Keep names unique. */
- collection_name_check(owner_id, sc_src);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ Collection *nested = collection_from_index_recursive(child->collection, index, index_current);
+ if (nested != NULL) {
+ return nested;
+ }
+ }
+ return NULL;
+}
- return true;
+/**
+ * Return Scene Collection for a given index.
+ *
+ * The index is calculated from top to bottom counting the children before the siblings.
+ */
+Collection *BKE_collection_from_index(Scene *scene, const int index)
+{
+ int index_current = 0;
+ Collection *master_collection = BKE_collection_master(scene);
+ return collection_from_index_recursive(master_collection, index, &index_current);
}
-bool BKE_collection_move_into(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+static bool collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
{
- /* Find the SceneCollection the sc_src belongs to */
- SceneCollection *sc_master = master_collection_from_id(owner_id);
- if (sc_src == sc_master) {
+ bool changed = false;
+
+ if (collection->flag & COLLECTION_RESTRICT_SELECT) {
return false;
}
- /* We can't move a collection if the destiny collection
- * is nested to the source collection */
- if (is_collection_in_tree(sc_dst, sc_src)) {
- return false;
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
+
+ if (base) {
+ if (deselect) {
+ if (base->flag & BASE_SELECTED) {
+ base->flag &= ~BASE_SELECTED;
+ changed = true;
+ }
+ }
+ else {
+ if ((base->flag & BASE_SELECTABLED) && !(base->flag & BASE_SELECTED)) {
+ base->flag |= BASE_SELECTED;
+ changed = true;
+ }
+ }
+ }
+ }
+
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ if (collection_objects_select(view_layer, collection, deselect)) {
+ changed = true;
+ }
}
- SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
- BLI_assert(sc_src_parent);
+ return changed;
+}
- /* collection is already where we wanted it to be */
- if (sc_dst->scene_collections.last == sc_src) {
+/**
+ * Select all the objects in this Collection (and its nested collections) for this ViewLayer.
+ * Return true if any object was selected.
+ */
+bool BKE_collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
+{
+ LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, collection);
+
+ if (layer_collection != NULL) {
+ return BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
+ }
+ else {
+ return collection_objects_select(view_layer, collection, deselect);
+ }
+}
+
+/***************** Collection move (outliner drag & drop) *********************/
+
+bool BKE_collection_move(Main *bmain,
+ Collection *to_parent,
+ Collection *from_parent,
+ Collection *relative,
+ bool relative_after,
+ Collection *collection)
+{
+ if (collection->flag & COLLECTION_IS_MASTER) {
return false;
}
+ if (BKE_collection_find_cycle(to_parent, collection)) {
+ return false;
+ }
+
+ /* Move to new parent collection */
+ if (from_parent) {
+ collection_child_remove(from_parent, collection);
+ }
+
+ collection_child_add(to_parent, collection, 0, true);
+
+ /* Move to specified location under parent. */
+ if (relative) {
+ CollectionChild *child = collection_find_child(to_parent, collection);
+ CollectionChild *relative_child = collection_find_child(to_parent, relative);
- /* Remove sc_src from it */
- BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+ if (relative_child) {
+ BLI_remlink(&to_parent->children, child);
- /* Insert sc_src into sc_dst */
- BLI_addtail(&sc_dst->scene_collections, sc_src);
+ if (relative_after) {
+ BLI_insertlinkafter(&to_parent->children, relative_child, child);
+ }
+ else {
+ BLI_insertlinkbefore(&to_parent->children, relative_child, child);
+ }
- /* Update the tree */
- BKE_layer_collection_resync(owner_id, sc_src_parent);
- BKE_layer_collection_resync(owner_id, sc_dst);
+ BKE_collection_object_cache_free(to_parent);
+ }
+ }
- /* Keep names unique. */
- collection_name_check(owner_id, sc_src);
+ BKE_main_collection_sync(bmain);
return true;
}
-/* ---------------------------------------------------------------------- */
-/* Iteractors */
+/**************************** Iterators ******************************/
+
/* scene collection iteractor */
-typedef struct SceneCollectionsIteratorData {
- ID *owner_id;
+typedef struct CollectionsIteratorData {
+ Scene *scene;
void **array;
int tot, cur;
-} SceneCollectionsIteratorData;
+} CollectionsIteratorData;
-static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
+static void scene_collection_callback(Collection *collection, BKE_scene_collections_Cb callback, void *data)
{
- callback(sc, data);
+ callback(collection, data);
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- scene_collection_callback(nsc, callback, data);
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ scene_collection_callback(child->collection, callback, data);
}
}
-static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
+static void scene_collections_count(Collection *UNUSED(collection), void *data)
{
int *tot = data;
(*tot)++;
}
-static void scene_collections_build_array(SceneCollection *sc, void *data)
+static void scene_collections_build_array(Collection *collection, void *data)
{
- SceneCollection ***array = data;
- **array = sc;
+ Collection ***array = data;
+ **array = collection;
(*array)++;
}
-static void scene_collections_array(ID *owner_id, SceneCollection ***collections_array, int *tot)
+static void scene_collections_array(Scene *scene, Collection ***collections_array, int *tot)
{
- SceneCollection *sc;
- SceneCollection **array;
+ Collection *collection;
+ Collection **array;
*collections_array = NULL;
*tot = 0;
- if (owner_id == NULL) {
+ if (scene == NULL) {
return;
}
- sc = master_collection_from_id(owner_id);
- BLI_assert(sc != NULL);
- scene_collection_callback(sc, scene_collections_count, tot);
+ collection = BKE_collection_master(scene);
+ BLI_assert(collection != NULL);
+ scene_collection_callback(collection, scene_collections_count, tot);
if (*tot == 0)
return;
- *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
- scene_collection_callback(sc, scene_collections_build_array, &array);
+ *collections_array = array = MEM_mallocN(sizeof(Collection *) * (*tot), "CollectionArray");
+ scene_collection_callback(collection, scene_collections_build_array, &array);
}
/**
@@ -873,14 +1064,14 @@ static void scene_collections_array(ID *owner_id, SceneCollection ***collections
*/
void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- ID *owner_id = data_in;
- SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __func__);
+ Scene *scene = data_in;
+ CollectionsIteratorData *data = MEM_callocN(sizeof(CollectionsIteratorData), __func__);
- data->owner_id = owner_id;
+ data->scene = scene;
iter->data = data;
iter->valid = true;
- scene_collections_array(owner_id, (SceneCollection ***)&data->array, &data->tot);
+ scene_collections_array(scene, (Collection ***)&data->array, &data->tot);
BLI_assert(data->tot != 0);
data->cur = 0;
@@ -889,7 +1080,7 @@ void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter)
{
- SceneCollectionsIteratorData *data = iter->data;
+ CollectionsIteratorData *data = iter->data;
if (++data->cur < data->tot) {
iter->current = data->array[data->cur];
@@ -901,7 +1092,7 @@ void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter)
void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter)
{
- SceneCollectionsIteratorData *data = iter->data;
+ CollectionsIteratorData *data = iter->data;
if (data) {
if (data->array) {
@@ -917,7 +1108,7 @@ void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter)
typedef struct SceneObjectsIteratorData {
GSet *visited;
- LinkData *link_next;
+ CollectionObject *cob_next;
BLI_Iterator scene_collection_iter;
} SceneObjectsIteratorData;
@@ -933,9 +1124,9 @@ void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
/* we wrap the scenecollection iterator here to go over the scene collections */
BKE_scene_collections_iterator_begin(&data->scene_collection_iter, scene);
- SceneCollection *sc = data->scene_collection_iter.current;
- if (sc->objects.first != NULL) {
- iter->current = ((LinkData *)sc->objects.first)->data;
+ Collection *collection = data->scene_collection_iter.current;
+ if (collection->gobject.first != NULL) {
+ iter->current = ((CollectionObject *)collection->gobject.first)->ob;
}
else {
BKE_scene_objects_iterator_next(iter);
@@ -945,14 +1136,14 @@ void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
/**
* Gets the first unique object in the sequence
*/
-static LinkData *object_base_unique(GSet *gs, LinkData *link)
+static CollectionObject *object_base_unique(GSet *gs, CollectionObject *cob)
{
- for (; link != NULL; link = link->next) {
- Object *ob = link->data;
+ for (; cob != NULL; cob = cob->next) {
+ Object *ob = cob->ob;
void **ob_key_p;
if (!BLI_gset_ensure_p_ex(gs, ob, &ob_key_p)) {
*ob_key_p = ob;
- return link;
+ return cob;
}
}
return NULL;
@@ -961,23 +1152,23 @@ static LinkData *object_base_unique(GSet *gs, LinkData *link)
void BKE_scene_objects_iterator_next(BLI_Iterator *iter)
{
SceneObjectsIteratorData *data = iter->data;
- LinkData *link = data->link_next ? object_base_unique(data->visited, data->link_next) : NULL;
+ CollectionObject *cob = data->cob_next ? object_base_unique(data->visited, data->cob_next) : NULL;
- if (link) {
- data->link_next = link->next;
- iter->current = link->data;
+ if (cob) {
+ data->cob_next = cob->next;
+ iter->current = cob->ob;
}
else {
- /* if this is the last object of this ListBase look at the next SceneCollection */
- SceneCollection *sc;
+ /* if this is the last object of this ListBase look at the next Collection */
+ Collection *collection;
BKE_scene_collections_iterator_next(&data->scene_collection_iter);
do {
- sc = data->scene_collection_iter.current;
+ collection = data->scene_collection_iter.current;
/* get the first unique object of this collection */
- LinkData *new_link = object_base_unique(data->visited, sc->objects.first);
- if (new_link) {
- data->link_next = new_link->next;
- iter->current = new_link->data;
+ CollectionObject *new_cob = object_base_unique(data->visited, collection->gobject.first);
+ if (new_cob) {
+ data->cob_next = new_cob->next;
+ iter->current = new_cob->ob;
return;
}
BKE_scene_collections_iterator_next(&data->scene_collection_iter);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index ee3c38b9282..b23b1b2dbed 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -46,8 +46,8 @@
#include "BLI_edgehash.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_effect.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
@@ -503,20 +503,20 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
/* objects in dupli groups, one level only for now */
if (ob->dup_group && level == 0) {
- Group *group= ob->dup_group;
+ Collection *collection= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
// return all collision objects in scene
// collision object will exclude self
-Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
+Object **get_collisionobjects_ext(Scene *scene, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
Object **objs;
unsigned int numobj= 0, maxobj= 100;
@@ -525,13 +525,13 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi
objs= MEM_callocN(sizeof(Object *)*maxobj, "CollisionObjectsArray");
/* gather all collision objects */
- if (group) {
- /* use specified group */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ if (collection) {
+ /* use specified collection */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
Scene *sce_iter;
@@ -549,11 +549,11 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi
return objs;
}
-Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type)
+Object **get_collisionobjects(Scene *scene, Object *self, Collection *collection, unsigned int *numcollobj, unsigned int modifier_type)
{
/* Need to check for active layers, too.
Otherwise this check fails if the objects are not on the same layer - DG */
- return get_collisionobjects_ext(scene, self, group, numcollobj, modifier_type, true);
+ return get_collisionobjects_ext(scene, self, collection, numcollobj, modifier_type, true);
}
static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
@@ -579,30 +579,30 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self,
BLI_addtail(*objs, col);
}
- /* objects in dupli groups, one level only for now */
+ /* objects in dupli collection, one level only for now */
if (ob->dup_group && level == 0) {
- Group *group= ob->dup_group;
+ Collection *collection= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collider_cache_object(objs, object, self, level+1);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
-ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
+ListBase *get_collider_cache(Scene *scene, Object *self, Collection *collection)
{
ListBase *objs= NULL;
/* add object in same layer in scene */
- if (group) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
+ if (collection) {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, object)
{
add_collider_cache_object(&objs, object, self, 0);
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
Scene *sce_iter;
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index f420fd974cd..6314486d809 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -30,6 +30,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -949,7 +950,7 @@ LayerCollection *CTX_data_layer_collection(const bContext *C)
LayerCollection *layer_collection;
if (ctx_data_pointer_verify(C, "layer_collection", (void *)&layer_collection)) {
- if (BKE_view_layer_has_collection(view_layer, layer_collection->scene_collection)) {
+ if (BKE_view_layer_has_collection(view_layer, layer_collection->collection)) {
return layer_collection;
}
}
@@ -958,21 +959,21 @@ LayerCollection *CTX_data_layer_collection(const bContext *C)
return BKE_layer_collection_get_active(view_layer);
}
-SceneCollection *CTX_data_scene_collection(const bContext *C)
+Collection *CTX_data_collection(const bContext *C)
{
- SceneCollection *scene_collection;
- if (ctx_data_pointer_verify(C, "scene_collection", (void *)&scene_collection)) {
- return scene_collection;
+ Collection *collection;
+ if (ctx_data_pointer_verify(C, "collection", (void *)&collection)) {
+ return collection;
}
LayerCollection *layer_collection = CTX_data_layer_collection(C);
if (layer_collection) {
- return layer_collection->scene_collection;
+ return layer_collection->collection;
}
/* fallback */
Scene *scene = CTX_data_scene(C);
- return BKE_collection_master(&scene->id);
+ return BKE_collection_master(scene);
}
int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectMode object_mode)
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 848e5fbe5f8..ee2ece48325 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -43,7 +43,7 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_dynamicpaint_types.h"
-#include "DNA_group_types.h" /*GroupObject*/
+#include "DNA_group_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -55,6 +55,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_bvhutils.h" /* bvh tree */
+#include "BKE_collection.h"
#include "BKE_colorband.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_constraint.h"
@@ -491,17 +492,12 @@ static void scene_setSubframe(Scene *scene, float subframe)
static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer)
{
- Base *base = NULL;
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, surface->brush_group);
Object *brushObj = NULL;
ModifierData *md = NULL;
int flags = 0;
- if (surface->brush_group)
- base = FIRSTBASE(surface->brush_group->view_layer);
- else
- base = FIRSTBASE(view_layer);
-
while (base) {
brushObj = NULL;
@@ -5911,21 +5907,15 @@ static int dynamicPaint_doStep(struct Depsgraph *depsgraph, Scene *scene, Object
* Loop through surface's target paint objects and do painting
*/
{
- Base *base = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, surface->brush_group);
/* backup current scene frame */
int scene_frame = scene->r.cfra;
float scene_subframe = scene->r.subframe;
- /* either from group or from all objects */
- if (surface->brush_group)
- base = FIRSTBASE(surface->brush_group->view_layer);
- else
- base = FIRSTBASE(view_layer);
-
while (base) {
brushObj = NULL;
/* select object */
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 8bdc74edffd..00c1c82bae8 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -57,6 +57,7 @@
#include "PIL_time.h"
#include "BKE_anim.h" /* needed for where_on_path */
+#include "BKE_collection.h"
#include "BKE_collision.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
@@ -64,7 +65,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
@@ -86,7 +86,7 @@
#include <string.h>
#endif // WITH_MOD_FLUID
-EffectorWeights *BKE_add_effector_weights(Group *group)
+EffectorWeights *BKE_add_effector_weights(Collection *collection)
{
EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights");
int i;
@@ -96,7 +96,7 @@ EffectorWeights *BKE_add_effector_weights(Group *group)
weights->global_gravity = 1.0f;
- weights->group = group;
+ weights->group = collection;
return weights;
}
@@ -215,23 +215,10 @@ ListBase *pdInitEffectors(
struct Depsgraph *depsgraph, Scene *scene, Object *ob_src, ParticleSystem *psys_src,
EffectorWeights *weights, bool for_simulation)
{
- ViewLayer *view_layer;
- Base *base;
+ Base *base = BKE_collection_or_layer_objects(depsgraph, scene, NULL, weights->group);
ListBase *effectors = NULL;
- if (weights->group) {
- view_layer = weights->group->view_layer;
- }
- /* TODO(mai): the check for view_layer shouldnt be needed, remove when render engine api is updated for this */
- else if (depsgraph && DEG_get_evaluated_view_layer(depsgraph)) {
- view_layer = DEG_get_evaluated_view_layer(depsgraph);
- }
- else {
- /* depsgraph is NULL during deg build */
- view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
- }
-
- for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (; base; base = base->next) {
if ((base->flag & BASE_VISIBLED) == 0) {
continue;
}
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index b656d2cf7c0..d439b5e7a6e 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -83,7 +83,7 @@ void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user)
BLI_freelistN(&config->modules);
}
-void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag)
+void BKE_freestyle_config_copy(FreestyleConfig *new_config, const FreestyleConfig *config, const int flag)
{
FreestyleLineSet *lineset, *new_lineset;
FreestyleModuleConfig *module, *new_module;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
deleted file mode 100644
index f2c9bfdd974..00000000000
--- a/source/blender/blenkernel/intern/group.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/group.c
- * \ingroup bke
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_group_types.h"
-#include "DNA_material_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_particle_types.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_collection.h"
-#include "BKE_global.h"
-#include "BKE_group.h"
-#include "BKE_icons.h"
-#include "BKE_layer.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_object.h"
-#include "BKE_scene.h"
-
-#include "DEG_depsgraph.h"
-
-/** Free (or release) any data used by this group (does not free the group itself). */
-void BKE_group_free(Group *group)
-{
- /* No animdata here. */
- BKE_previewimg_free(&group->preview);
-
- if (group->view_layer != NULL) {
- BKE_view_layer_free(group->view_layer);
- group->view_layer = NULL;
- }
-
- if (group->collection != NULL) {
- BKE_collection_master_free(&group->id, false);
- MEM_freeN(group->collection);
- group->collection = NULL;
- }
-}
-
-/**
- * Run when adding new groups or during doversion.
- */
-void BKE_group_init(Group *group)
-{
- group->collection = MEM_callocN(sizeof(SceneCollection), __func__);
- BLI_strncpy(group->collection->name, "Master Collection", sizeof(group->collection->name));
- group->view_layer = BKE_view_layer_group_add(group);
-
- /* Unlink the master collection. */
- BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.first);
-
- /* Create and link a new default collection. */
- SceneCollection *defaut_collection = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
- BKE_collection_link(group->view_layer, defaut_collection);
-}
-
-Group *BKE_group_add(Main *bmain, const char *name)
-{
- Group *group;
-
- group = BKE_libblock_alloc(bmain, ID_GR, name, 0);
- id_us_min(&group->id);
- id_us_ensure_real(&group->id);
- group->layer = (1 << 20) - 1;
-
- group->preview = NULL;
- BKE_group_init(group);
- return group;
-}
-
-/**
- * Only copy internal data of Group ID from source to already allocated/initialized destination.
- * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
- *
- * WARNING! This function will not handle ID user count!
- *
- * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
- */
-void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag)
-{
- /* We never handle usercount here for own data. */
- const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
-
- /* Do not copy group's preview (same behavior as for objects). */
- if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
- BKE_previewimg_id_copy(&group_dst->id, &group_src->id);
- }
- else {
- group_dst->preview = NULL;
- }
-
- group_dst->collection = MEM_dupallocN(group_src->collection);
- SceneCollection *master_collection_src = BKE_collection_master(&group_src->id);
- SceneCollection *master_collection_dst = BKE_collection_master(&group_dst->id);
-
- /* Recursively creates a new SceneCollection tree. */
- BKE_collection_copy_data(master_collection_dst, master_collection_src,
- flag_subdata);
-
- group_dst->view_layer = MEM_dupallocN(group_src->view_layer);
- BKE_view_layer_copy_data(group_dst->view_layer, group_src->view_layer,
- master_collection_dst, master_collection_src,
- flag_subdata);
-}
-
-Group *BKE_group_copy(Main *bmain, const Group *group)
-{
- Group *group_copy;
- BKE_id_copy_ex(bmain, &group->id, (ID **)&group_copy, 0, false);
- return group_copy;
-}
-
-void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local)
-{
- BKE_id_make_local_generic(bmain, &group->id, true, lib_local);
-}
-
-/* external */
-static bool group_object_add_internal(Group *group, Object *ob)
-{
- if (group == NULL || ob == NULL) {
- return false;
- }
-
- /* For now always add to master collection of the group. */
- SceneCollection *scene_collection = GROUP_MASTER_COLLECTION(group);
-
- /* If the object has been added already it returns false. */
- if (BKE_collection_object_add(&group->id, scene_collection, ob) == false) {
- return false;
- }
-
- id_us_ensure_real(&ob->id);
- return true;
-}
-
-bool BKE_group_object_add(Group *group, Object *object)
-{
- if (group_object_add_internal(group, object)) {
- if ((object->flag & OB_FROMGROUP) == 0) {
- object->flag |= OB_FROMGROUP;
- }
- return true;
- }
- else {
- return false;
- }
-}
-
-/* also used for (ob == NULL) */
-static bool group_object_unlink_internal(Group *group, Object *ob)
-{
- if (group == NULL) {
- return false;
- }
-
- if (BKE_collections_object_remove(NULL, &group->id, ob, false)) {
- return true;
- }
-
- return false;
-}
-
-static bool group_object_cyclic_check_internal(Object *object, Group *group)
-{
- if (object->dup_group) {
- Group *dup_group = object->dup_group;
- if ((dup_group->id.tag & LIB_TAG_DOIT) == 0) {
- /* Cycle already exists in groups, let's prevent further crappyness */
- return true;
- }
- /* flag the object to identify cyclic dependencies in further dupli groups */
- dup_group->id.tag &= ~LIB_TAG_DOIT;
-
- if (dup_group == group)
- return true;
- else {
- FOREACH_GROUP_OBJECT_BEGIN(dup_group, group_object)
- {
- if (group_object_cyclic_check_internal(group_object, dup_group)) {
- return true;
- }
- }
- FOREACH_GROUP_OBJECT_END;
- }
-
- /* un-flag the object, it's allowed to have the same group multiple times in parallel */
- dup_group->id.tag |= LIB_TAG_DOIT;
- }
-
- return false;
-}
-
-bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
-{
- /* first flag all groups */
- BKE_main_id_tag_listbase(&bmain->group, LIB_TAG_DOIT, true);
-
- return group_object_cyclic_check_internal(object, group);
-}
-
-bool BKE_group_object_unlink(Group *group, Object *object)
-{
- if (group_object_unlink_internal(group, object)) {
- /* object can be NULL */
- if (object && BKE_group_object_find(NULL, object) == NULL) {
- object->flag &= ~OB_FROMGROUP;
- }
- return true;
- }
- else {
- return false;
- }
-}
-
-bool BKE_group_object_exists(Group *group, Object *ob)
-{
- if (group == NULL || ob == NULL) {
- return false;
- }
- else {
- return (BLI_findptr(&group->view_layer->object_bases, ob, offsetof(Base, object)));
- }
-}
-
-Group *BKE_group_object_find(Group *group, Object *ob)
-{
- if (group)
- group = group->id.next;
- else
- group = G.main->group.first;
-
- while (group) {
- if (BKE_group_object_exists(group, ob))
- return group;
- group = group->id.next;
- }
- return NULL;
-}
-
-bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
-{
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->proxy) {
- return true;
- }
- }
- FOREACH_GROUP_OBJECT_END;
- return false;
-}
-
-#if 0 // add back when timeoffset & animsys work again
-/* only replaces object strips or action when parent nla instructs it */
-/* keep checking nla.c though, in case internal structure of strip changes */
-static void group_replaces_nla(Object *parent, Object *target, char mode)
-{
- static ListBase nlastrips = {NULL, NULL};
- static bAction *action = NULL;
- static bool done = false;
- bActionStrip *strip, *nstrip;
-
- if (mode == 's') {
-
- for (strip = parent->nlastrips.first; strip; strip = strip->next) {
- if (strip->object == target) {
- if (done == 0) {
- /* clear nla & action from object */
- nlastrips = target->nlastrips;
- BLI_listbase_clear(&target->nlastrips);
- action = target->action;
- target->action = NULL;
- target->nlaflag |= OB_NLA_OVERRIDE;
- done = true;
- }
- nstrip = MEM_dupallocN(strip);
- BLI_addtail(&target->nlastrips, nstrip);
- }
- }
- }
- else if (mode == 'e') {
- if (done) {
- BLI_freelistN(&target->nlastrips);
- target->nlastrips = nlastrips;
- target->action = action;
-
- BLI_listbase_clear(&nlastrips); /* not needed, but yah... :) */
- action = NULL;
- done = false;
- }
- }
-}
-#endif
-
-/* puts all group members in local timing system, after this call
- * you can draw everything, leaves tags in objects to signal it needs further updating */
-
-/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void BKE_group_handle_recalc_and_update(struct Depsgraph *depsgraph, Scene *scene, Object *UNUSED(parent), Group *group)
-{
-#if 0 /* warning, isn't clearing the recalc flag on the object which causes it to run all the time,
- * not just on frame change.
- * This isn't working because the animation data is only re-evaluated on frame change so commenting for now
- * but when its enabled at some point it will need to be changed so as not to update so much - campbell */
-
- /* if animated group... */
- if (parent->nlastrips.first) {
- int cfrao;
-
- /* switch to local time */
- cfrao = scene->r.cfra;
-
- /* we need a DAG per group... */
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob && go->recalc) {
- go->ob->recalc = go->recalc;
-
- group_replaces_nla(parent, go->ob, 's');
- BKE_object_handle_update(depsgraph, scene, go->ob);
- group_replaces_nla(parent, go->ob, 'e');
-
- /* leave recalc tags in case group members are in normal scene */
- go->ob->recalc = go->recalc;
- }
- }
-
- /* restore */
- scene->r.cfra = cfrao;
- }
- else
-#endif
- {
- /* only do existing tags, as set by regular depsgraph */
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- if (object->id.recalc & ID_RECALC_ALL) {
- BKE_object_handle_update(depsgraph, scene, object);
- }
- }
- FOREACH_GROUP_OBJECT_END;
- }
-}
-
-/* ******** Dependency graph evaluation ******** */
-
-void BKE_group_eval_view_layers(struct Depsgraph *depsgraph,
- Group *group)
-{
- DEG_debug_print_eval(depsgraph, __func__, group->id.name, group);
- BKE_layer_eval_view_layer(depsgraph, &group->id, group->view_layer);
-}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 61c05c2500d..8476bb6b66d 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -322,7 +322,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id)
ID_PRV_CASE(ID_IM, Image);
ID_PRV_CASE(ID_BR, Brush);
ID_PRV_CASE(ID_OB, Object);
- ID_PRV_CASE(ID_GR, Group);
+ ID_PRV_CASE(ID_GR, Collection);
ID_PRV_CASE(ID_SCE, Scene);
ID_PRV_CASE(ID_SCR, bScreen);
#undef ID_PRV_CASE
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 487635f06ad..4860f5a896d 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -61,9 +61,9 @@ static IDType idtypes[] = {
{ ID_BR, "Brush", "brushes", BLT_I18NCONTEXT_ID_BRUSH, IDTYPE_FLAGS_ISLINKABLE },
{ ID_CA, "Camera", "cameras", BLT_I18NCONTEXT_ID_CAMERA, IDTYPE_FLAGS_ISLINKABLE },
{ ID_CF, "CacheFile", "cache_files", BLT_I18NCONTEXT_ID_CACHEFILE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_GR, "Collection", "collections", BLT_I18NCONTEXT_ID_COLLECTION, IDTYPE_FLAGS_ISLINKABLE },
{ ID_CU, "Curve", "curves", BLT_I18NCONTEXT_ID_CURVE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_GD, "GPencil", "grease_pencil", BLT_I18NCONTEXT_ID_GPENCIL, IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
- { ID_GR, "Group", "groups", BLT_I18NCONTEXT_ID_GROUP, IDTYPE_FLAGS_ISLINKABLE },
{ ID_IM, "Image", "images", BLT_I18NCONTEXT_ID_IMAGE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_IP, "Ipo", "ipos", "", IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */
{ ID_KE, "Key", "shape_keys", BLT_I18NCONTEXT_ID_SHAPEKEY, 0 },
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index da068802586..685c007da6b 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -31,12 +31,12 @@
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
+#include "BLI_threads.h"
#include "BLT_translation.h"
#include "BKE_collection.h"
#include "BKE_freestyle.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@@ -61,24 +61,51 @@
#include "MEM_guardedalloc.h"
+
/* prototype */
-struct EngineSettingsCB_Type;
-static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src);
-static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
-static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects);
-static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc);
-static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
static void object_bases_iterator_next(BLI_Iterator *iter, const int flag);
+
+/*********************** Layer Collections and bases *************************/
+
+static LayerCollection *layer_collection_add(ListBase *lb_parent, Collection *collection)
+{
+ LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+ lc->collection = collection;
+ BLI_addtail(lb_parent, lc);
+
+ return lc;
+}
+
+static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if (lc == view_layer->active_collection) {
+ view_layer->active_collection = view_layer->layer_collections.first;
+ }
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_free(view_layer, nlc);
+ }
+
+ BLI_freelistN(&lc->layer_collections);
+}
+
+static Base *object_base_new(Object *ob)
+{
+ Base *base = MEM_callocN(sizeof(Base), "Object Base");
+ base->object = ob;
+ return base;
+}
+
+/********************************* View Layer ********************************/
+
+
/* RenderLayer */
/* Returns the default view layer to view in workspaces if there is
* none linked to the workspace yet. */
ViewLayer *BKE_view_layer_default_view(const Scene *scene)
{
- /* TODO: it makes more sense to have the Viewport layer as the default,
- * but this breaks view layer tests so change it later. */
-#if 0
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
if (!(view_layer->flag & VIEW_LAYER_RENDER)) {
return view_layer;
@@ -87,9 +114,6 @@ ViewLayer *BKE_view_layer_default_view(const Scene *scene)
BLI_assert(scene->view_layers.first);
return scene->view_layers.first;
-#else
- return BKE_view_layer_default_render(scene);
-#endif
}
/* Returns the default view layer to render if we need to render just one. */
@@ -123,7 +147,7 @@ ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene)
return scene->view_layers.first;
}
-static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene_collection)
+static ViewLayer *view_layer_add(const char *name)
{
if (!name) {
name = DATA_("View Layer");
@@ -134,9 +158,6 @@ static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene
BLI_strncpy_utf8(view_layer->name, name, sizeof(view_layer->name));
- /* Link the master collection by default. */
- layer_collection_add(view_layer, NULL, master_scene_collection);
-
/* Pure rendering pipeline settings. */
view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */
view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
@@ -152,8 +173,7 @@ static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene
*/
ViewLayer *BKE_view_layer_add(Scene *scene, const char *name)
{
- SceneCollection *sc = BKE_collection_master(&scene->id);
- ViewLayer *view_layer = view_layer_add(name, sc);
+ ViewLayer *view_layer = view_layer_add(name);
BLI_addtail(&scene->view_layers, view_layer);
@@ -162,18 +182,8 @@ ViewLayer *BKE_view_layer_add(Scene *scene, const char *name)
&scene->view_layers, view_layer, DATA_("ViewLayer"), '.',
offsetof(ViewLayer, name), sizeof(view_layer->name));
- return view_layer;
-}
+ BKE_layer_collection_sync(scene, view_layer);
-/**
- * Add a ViewLayer for a Group
- * It should be added only once
- */
-ViewLayer *BKE_view_layer_group_add(Group *group)
-{
- BLI_assert(group->view_layer == NULL);
- SceneCollection *sc = BKE_collection_master(&group->id);
- ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc);
return view_layer;
}
@@ -191,8 +201,12 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
BLI_freelistN(&view_layer->object_bases);
+ if (view_layer->object_bases_hash) {
+ BLI_ghash_free(view_layer->object_bases_hash, NULL, NULL);
+ }
+
for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- layer_collection_free(NULL, lc);
+ layer_collection_free(view_layer, lc);
}
BLI_freelistN(&view_layer->layer_collections);
@@ -235,22 +249,6 @@ void BKE_view_layer_selected_objects_tag(ViewLayer *view_layer, const int tag)
}
}
-/**
- * Return the first ViewLayer for a given id
- */
-ViewLayer *BKE_view_layer_first_from_id(const ID *owner_id)
-{
- switch (GS(owner_id->name)) {
- case ID_SCE:
- return ((Scene *)owner_id)->view_layers.first;
- case ID_GR:
- return ((Group *)owner_id)->view_layer;
- default:
- BLI_assert(!"ID doesn't support view layers");
- return NULL;
- }
-}
-
static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
{
for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
@@ -285,32 +283,43 @@ Object *BKE_view_layer_camera_find(ViewLayer *view_layer)
/**
* Find the ViewLayer a LayerCollection belongs to
*/
-ViewLayer *BKE_view_layer_find_from_collection(const ID *owner_id, LayerCollection *lc)
+ViewLayer *BKE_view_layer_find_from_collection(const Scene *scene, LayerCollection *lc)
{
- switch (GS(owner_id->name)) {
- case ID_GR:
- return ((Group *)owner_id)->view_layer;
- case ID_SCE:
- {
- Scene *scene = (Scene *)owner_id;
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
- if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) {
- return view_layer;
- }
- }
- return NULL;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) {
+ return view_layer;
}
- default:
- BLI_assert(!"ID doesn't support scene layers");
- return NULL;
}
+
+ return NULL;
}
/* Base */
+static void view_layer_bases_hash_create(ViewLayer *view_layer)
+{
+ static ThreadMutex hash_lock = BLI_MUTEX_INITIALIZER;
+
+ if (!view_layer->object_bases_hash) {
+ BLI_mutex_lock(&hash_lock);
+
+ view_layer->object_bases_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ BLI_ghash_insert(view_layer->object_bases_hash, base->object, base);
+ }
+
+ BLI_mutex_unlock(&hash_lock);
+ }
+}
+
Base *BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
{
- return BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object));
+ if (!view_layer->object_bases_hash) {
+ view_layer_bases_hash_create(view_layer);
+ }
+
+ return BLI_ghash_lookup(view_layer->object_bases_hash, ob);
}
void BKE_view_layer_base_deselect_all(ViewLayer *view_layer)
@@ -330,134 +339,32 @@ void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase)
}
}
-/****************************************************************************/
-/* Copying functions for datablocks that use ViewLayer/SceneCollection */
+/**************************** Copy View Layer and Layer Collections ***********************/
-/* Find the equivalent SceneCollection in the new tree */
-static SceneCollection *scene_collection_from_new_tree(
- SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src)
+static void layer_collections_copy_data(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
{
- if (sc_src == sc_reference) {
- return sc_dst;
- }
+ BLI_duplicatelist(layer_collections_dst, layer_collections_src);
- for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first;
- nsc_src;
- nsc_src = nsc_src->next, nsc_dst = nsc_dst->next)
- {
- SceneCollection *found = scene_collection_from_new_tree(sc_reference, nsc_dst, nsc_src);
- if (found != NULL) {
- return found;
- }
- }
- return NULL;
-}
-
-static void layer_collection_sync_flags(
- LayerCollection *layer_collection_dst,
- const LayerCollection *layer_collection_src)
-{
- layer_collection_dst->flag = layer_collection_src->flag;
-
- layer_collections_sync_flags(&layer_collection_dst->layer_collections,
- &layer_collection_src->layer_collections);
-}
+ LayerCollection *layer_collection_dst = layer_collections_dst->first;
+ const LayerCollection *layer_collection_src = layer_collections_src->first;
-static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
-{
- BLI_assert(BLI_listbase_count(layer_collections_dst) == BLI_listbase_count(layer_collections_src));
- LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first;
- const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first;
while (layer_collection_dst != NULL) {
- layer_collection_sync_flags(layer_collection_dst, layer_collection_src);
+ layer_collections_copy_data(&layer_collection_dst->layer_collections,
+ &layer_collection_src->layer_collections);
+
layer_collection_dst = layer_collection_dst->next;
layer_collection_src = layer_collection_src->next;
}
}
-static bool layer_collection_sync_if_match(
- ListBase *lb,
- const SceneCollection *scene_collection_dst,
- const SceneCollection *scene_collection_src)
-{
- for (LayerCollection *layer_collection = lb->first;
- layer_collection;
- layer_collection = layer_collection->next)
- {
- if (layer_collection->scene_collection == scene_collection_src) {
- LayerCollection *layer_collection_dst =
- BLI_findptr(
- lb,
- scene_collection_dst,
- offsetof(LayerCollection, scene_collection));
-
- if (layer_collection_dst != NULL) {
- layer_collection_sync_flags(layer_collection_dst, layer_collection);
- }
- return true;
- }
- else {
- if (layer_collection_sync_if_match(
- &layer_collection->layer_collections,
- scene_collection_dst,
- scene_collection_src))
- {
- return true;
- }
- }
- }
- return false;
-}
-
-/**
- * Sync sibling collections across all view layers
- *
- * Make sure every linked instance of \a scene_collection_dst has the same values
- * (flags, overrides, ...) as the corresponding scene_collection_src.
- *
- * \note expect scene_collection_dst to be scene_collection_src->next, and it also
- * expects both collections to have the same ammount of sub-collections.
- */
-void BKE_layer_collection_sync_flags(
- ID *owner_id,
- SceneCollection *scene_collection_dst,
- SceneCollection *scene_collection_src)
-{
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- for (LayerCollection *layer_collection = view_layer->layer_collections.first;
- layer_collection;
- layer_collection = layer_collection->next)
- {
- layer_collection_sync_if_match(
- &layer_collection->layer_collections,
- scene_collection_dst,
- scene_collection_src);
- }
- }
-}
-
-/* recreate the LayerCollection tree */
-static void layer_collections_recreate(
- ViewLayer *view_layer_dst, ListBase *lb_src, SceneCollection *mc_dst, SceneCollection *mc_src)
-{
- for (LayerCollection *lc_src = lb_src->first; lc_src; lc_src = lc_src->next) {
- SceneCollection *sc_dst = scene_collection_from_new_tree(lc_src->scene_collection, mc_dst, mc_src);
- BLI_assert(sc_dst);
-
- /* instead of synchronizing both trees we simply re-create it */
- BKE_collection_link(view_layer_dst, sc_dst);
- }
-}
-
/**
* Only copy internal data of ViewLayer from source to already allocated/initialized destination.
*
- * \param mc_src Master Collection the source ViewLayer links in.
- * \param mc_dst Master Collection the destination ViewLayer links in.
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
void BKE_view_layer_copy_data(
- ViewLayer *view_layer_dst, ViewLayer *view_layer_src, SceneCollection *mc_dst, SceneCollection *mc_src,
+ Scene *UNUSED(scene_dst), const Scene *UNUSED(scene_src),
+ ViewLayer *view_layer_dst, const ViewLayer *view_layer_src,
const int flag)
{
if (view_layer_dst->id_properties != NULL) {
@@ -467,176 +374,16 @@ void BKE_view_layer_copy_data(
view_layer_dst->stats = NULL;
- /* we start fresh with no overrides and no visibility flags set
- * instead of syncing both trees we simply unlink and relink the scene collection */
- BLI_listbase_clear(&view_layer_dst->layer_collections);
- BLI_listbase_clear(&view_layer_dst->object_bases);
+ /* Clear temporary data. */
BLI_listbase_clear(&view_layer_dst->drawdata);
-
- layer_collections_recreate(view_layer_dst, &view_layer_src->layer_collections, mc_dst, mc_src);
-
- /* Now we handle the syncing for visibility, selectability, ... */
- layer_collections_sync_flags(&view_layer_dst->layer_collections, &view_layer_src->layer_collections);
-
- Object *active_ob = OBACT(view_layer_src);
- for (Base *base_src = view_layer_src->object_bases.first, *base_dst = view_layer_dst->object_bases.first;
- base_src;
- base_src = base_src->next, base_dst = base_dst->next)
- {
- base_dst->flag = base_src->flag;
- base_dst->flag_legacy = base_src->flag_legacy;
-
- if (base_dst->object == active_ob) {
- view_layer_dst->basact = base_dst;
- }
- }
-
view_layer_dst->object_bases_array = NULL;
-}
-
-/**
- * Find and return the ListBase of LayerCollection that has \a lc_child as one of its directly
- * nested LayerCollection.
- *
- * \param lb_parent Initial ListBase of LayerCollection to look into recursively
- * usually the view layer's collection list
- */
-static ListBase *find_layer_collection_parent_list_base(ListBase *lb_parent, const LayerCollection *lc_child)
-{
- for (LayerCollection *lc_nested = lb_parent->first; lc_nested; lc_nested = lc_nested->next) {
- if (lc_nested == lc_child) {
- return lb_parent;
- }
+ view_layer_dst->object_bases_hash = NULL;
- ListBase *found = find_layer_collection_parent_list_base(&lc_nested->layer_collections, lc_child);
- if (found != NULL) {
- return found;
- }
- }
+ /* Copy layer collections and object bases. */
+ BLI_duplicatelist(&view_layer_dst->object_bases, &view_layer_src->object_bases);
+ layer_collections_copy_data(&view_layer_dst->layer_collections, &view_layer_src->layer_collections);
- return NULL;
-}
-
-/**
- * Makes a shallow copy of a LayerCollection
- *
- * Add a new collection in the same level as the old one (linking if necessary),
- * and copy all the collection data across them.
- */
-struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection)
-{
- SceneCollection *scene_collection, *scene_collection_new;
-
- scene_collection = layer_collection->scene_collection;
- scene_collection_new = BKE_collection_duplicate(owner_id, scene_collection);
-
- LayerCollection *layer_collection_new = NULL;
-
- /* If the original layer_collection was directly linked to the view layer
- we need to link the new scene collection here as well. */
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- if (BLI_findindex(&view_layer->layer_collections, layer_collection) != -1) {
- layer_collection_new = BKE_collection_link(view_layer, scene_collection_new);
- layer_collection_sync_flags(layer_collection_new, layer_collection);
-
- if (layer_collection_new != layer_collection->next) {
- BLI_remlink(&view_layer->layer_collections, layer_collection_new);
- BLI_insertlinkafter(&view_layer->layer_collections, layer_collection, layer_collection_new);
- }
- break;
- }
- }
-
- /* Otherwise just try to find the corresponding layer collection to return it back. */
- if (layer_collection_new == NULL) {
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- ListBase *layer_collections_parent;
- layer_collections_parent = find_layer_collection_parent_list_base(
- &view_layer->layer_collections,
- layer_collection);
- if (layer_collections_parent != NULL) {
- layer_collection_new = BLI_findptr(
- layer_collections_parent,
- scene_collection_new,
- offsetof(LayerCollection, scene_collection));
- break;
- }
- }
- }
- return layer_collection_new;
-}
-
-static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base)
-{
- base->refcount--;
-
- /* It only exists in the RenderLayer */
- if (base->refcount == 0) {
- if (view_layer->basact == base) {
- view_layer->basact = NULL;
- }
-
- BLI_remlink(&view_layer->object_bases, base);
- MEM_freeN(base);
- }
-}
-
-/**
- * Return the base if existent, or create it if necessary
- * Always bump the refcount
- */
-static Base *object_base_add(ViewLayer *view_layer, Object *ob)
-{
- Base *base;
- base = BKE_view_layer_base_find(view_layer, ob);
-
- if (base == NULL) {
- base = MEM_callocN(sizeof(Base), "Object Base");
-
- /* Do not bump user count, leave it for SceneCollections. */
- base->object = ob;
- BLI_addtail(&view_layer->object_bases, base);
- }
-
- base->refcount++;
- return base;
-}
-
-/* LayerCollection */
-
-static void layer_collection_objects_unpopulate(ViewLayer *view_layer, LayerCollection *lc)
-{
- if (view_layer) {
- for (LinkData *link = lc->object_bases.first; link; link = link->next) {
- view_layer_object_base_unref(view_layer, link->data);
- }
- }
-
- BLI_freelistN(&lc->object_bases);
-}
-
-/**
- * When freeing the entire ViewLayer at once we don't bother with unref
- * otherwise ViewLayer is passed to keep the syncing of the LayerCollection tree
- */
-static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
-{
- layer_collection_objects_unpopulate(view_layer, lc);
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- layer_collection_free(view_layer, nlc);
- }
-
- BLI_freelistN(&lc->layer_collections);
-}
-
-/**
- * Free (or release) LayerCollection from ViewLayer
- * (does not free the LayerCollection itself).
- */
-void BKE_layer_collection_free(ViewLayer *view_layer, LayerCollection *lc)
-{
- layer_collection_free(view_layer, lc);
+ // TODO: not always safe to free BKE_layer_collection_sync(scene_dst, view_layer_dst);
}
/* LayerCollection */
@@ -675,28 +422,46 @@ LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const in
*/
LayerCollection *BKE_layer_collection_get_active(ViewLayer *view_layer)
{
- int i = 0;
- return collection_from_index(&view_layer->layer_collections, view_layer->active_collection, &i);
+ return view_layer->active_collection;
}
+/*
+ * Activate collection
+ */
+bool BKE_layer_collection_activate(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ return false;
+ }
+
+ view_layer->active_collection = lc;
+ return true;
+}
/**
- * Return layer collection to add new object(s).
- * Create one if none exists.
+ * Activate first parent collection
*/
-LayerCollection *BKE_layer_collection_get_active_ensure(Scene *scene, ViewLayer *view_layer)
+LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, LayerCollection *lc)
{
- LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+ CollectionParent *parent = lc->collection->parents.first;
+
+ if (parent) {
+ lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection);
+ }
+ else {
+ lc = NULL;
+ }
+
+ if (lc && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ /* Don't activate excluded collections. */
+ return BKE_layer_collection_activate_parent(view_layer, lc);
+ }
- if (lc == NULL) {
- BLI_assert(BLI_listbase_is_empty(&view_layer->layer_collections));
- /* When there is no collection linked to this ViewLayer, create one. */
- SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL);
- lc = BKE_collection_link(view_layer, sc);
- /* New collection has to be the active one. */
- BLI_assert(lc == BKE_layer_collection_get_active(view_layer));
+ if (!lc) {
+ lc = view_layer->layer_collections.first;
}
+ view_layer->active_collection = lc;
return lc;
}
@@ -750,348 +515,208 @@ int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection
return index_from_collection(&view_layer->layer_collections, lc, &i);
}
-/**
- * Lookup the listbase that contains \a lc.
- */
-static ListBase *layer_collection_listbase_find(ListBase *lb, LayerCollection *lc)
-{
- for (LayerCollection *lc_iter = lb->first; lc_iter; lc_iter = lc_iter->next) {
- if (lc_iter == lc) {
- return lb;
+/*********************************** Syncing *********************************
+ *
+ * The layer collection tree mirrors the scene collection tree. Whenever that
+ * changes we need to synchronize them so that there is a corresponding layer
+ * collection for each collection. Note that the scene collection tree can
+ * contain link or override collections, and so this is also called on .blend
+ * file load to ensure any new or removed collections are synced.
+ *
+ * The view layer also contains a list of bases for each object that exists
+ * in at least one layer collection. That list is also synchronized here, and
+ * stores state like selection. */
+
+static void layer_collection_sync(ViewLayer *view_layer,
+ const ListBase *lb_scene,
+ ListBase *lb_layer,
+ ListBase *new_object_bases,
+ int parent_exclude,
+ int parent_restrict)
+{
+ /* TODO: support recovery after removal of intermediate collections, reordering, ..
+ * For local edits we can make editing operating do the appropriate thing, but for
+ * linking we can only sync after the fact. */
+
+ /* Remove layer collections that no longer have a corresponding scene collection. */
+ for (LayerCollection *lc = lb_layer->first; lc;) {
+ /* Note ID remap can set lc->collection to NULL when deleting collections. */
+ LayerCollection *lc_next = lc->next;
+ Collection *collection = (lc->collection) ? BLI_findptr(lb_scene, lc->collection, offsetof(CollectionChild, collection)) : NULL;
+
+ if (!collection) {
+ /* Free recursively. */
+ layer_collection_free(view_layer, lc);
+ BLI_freelinkN(lb_layer, lc);
}
- ListBase *lb_child_result;
- if ((lb_child_result = layer_collection_listbase_find(&lc_iter->layer_collections, lc))) {
- return lb_child_result;
- }
+ lc = lc_next;
}
- return NULL;
-}
+ /* Add layer collections for any new scene collections, and ensure order is the same. */
+ ListBase new_lb_layer = {NULL, NULL};
-#if 0
-/**
- * Lookup the listbase that contains \a sc.
- */
-static ListBase *scene_collection_listbase_find(ListBase *lb, SceneCollection *sc)
-{
- for (SceneCollection *sc_iter = lb->first; sc_iter; sc_iter = sc_iter->next) {
- if (sc_iter == sc) {
- return lb;
+ for (const CollectionChild *child = lb_scene->first; child; child = child->next) {
+ Collection *collection = child->collection;
+ LayerCollection *lc = BLI_findptr(lb_layer, collection, offsetof(LayerCollection, collection));
+
+ if (lc) {
+ BLI_remlink(lb_layer, lc);
+ BLI_addtail(&new_lb_layer, lc);
+ }
+ else {
+ lc = layer_collection_add(&new_lb_layer, collection);
+ lc->flag = parent_exclude;
}
- ListBase *lb_child_result;
- if ((lb_child_result = scene_collection_listbase_find(&sc_iter->scene_collections, sc))) {
- return lb_child_result;
+ /* Collection restrict is inherited. */
+ int child_restrict = parent_restrict;
+ if (!(collection->flag & COLLECTION_IS_MASTER)) {
+ child_restrict |= collection->flag;
}
- }
- return NULL;
-}
-#endif
+ /* Sync child collections. */
+ layer_collection_sync(view_layer, &collection->children, &lc->layer_collections, new_object_bases, lc->flag, child_restrict);
-/* ---------------------------------------------------------------------- */
-/* Outliner drag and drop */
+ /* Layer collection exclude is not inherited. */
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ continue;
+ }
-/**
- * Nest a LayerCollection into another one
- * Both collections must be from the same ViewLayer, return true if succeded.
- *
- * The LayerCollection will effectively be moved into the
- * new (nested) position. So all the settings, overrides, ... go with it, and
- * if the collection was directly linked to the ViewLayer it's then unlinked.
- *
- * For the other ViewLayers we simply resync the tree, without changing directly
- * linked collections (even if they link to the same SceneCollection)
- *
- * \param lc_src LayerCollection to nest into \a lc_dst
- * \param lc_dst LayerCollection to have \a lc_src inserted into
- */
+ /* Sync objects, except if collection was excluded. */
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BLI_ghash_lookup(view_layer->object_bases_hash, cob->ob);
+
+ if (base) {
+ /* Move from old base list to new base list. Base might have already
+ * been moved to the new base list and the first/last test ensure that
+ * case also works. */
+ if (!ELEM(base, new_object_bases->first, new_object_bases->last)) {
+ BLI_remlink(&view_layer->object_bases, base);
+ BLI_addtail(new_object_bases, base);
+ }
+ }
+ else {
+ /* Create new base. */
+ base = object_base_new(cob->ob);
+ BLI_addtail(new_object_bases, base);
+ BLI_ghash_insert(view_layer->object_bases_hash, base->object, base);
+ }
-static void layer_collection_swap(
- ViewLayer *view_layer, ListBase *lb_a, ListBase *lb_b,
- LayerCollection *lc_a, LayerCollection *lc_b)
-{
- if (lb_a == NULL) {
- lb_a = layer_collection_listbase_find(&view_layer->layer_collections, lc_a);
- }
+ if ((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) {
+ base->flag |= BASE_VISIBLED | BASE_VISIBLE_VIEWPORT;
- if (lb_b == NULL) {
- lb_b = layer_collection_listbase_find(&view_layer->layer_collections, lc_b);
+ if ((child_restrict & COLLECTION_RESTRICT_SELECT) == 0) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+ if ((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
+ base->flag |= BASE_VISIBLE_RENDER;
+ }
+ }
}
- BLI_assert(lb_a);
- BLI_assert(lb_b);
-
- BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b);
+ /* Replace layer collection list with new one. */
+ *lb_layer = new_lb_layer;
+ BLI_assert(BLI_listbase_count(lb_scene) == BLI_listbase_count(lb_layer));
}
/**
- * Move \a lc_src into \a lc_dst. Both have to be stored in \a view_layer.
- * If \a lc_src is directly linked to the ViewLayer it's unlinked
+ * Update view layer collection tree from collections used in the scene.
+ * This is used when collections are removed or added, both while editing
+ * and on file loaded in case linked data changed or went missing.
*/
-bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
{
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src);
- bool is_directly_linked = false;
-
- if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
- return false;
- }
-
- /* We can't nest the collection into itself */
- if (lc_src->scene_collection == lc_dst->scene_collection) {
- return false;
- }
-
- /* Collection is already where we wanted it to be */
- if (lc_dst->layer_collections.last == lc_src) {
- return false;
+ if (!scene->master_collection) {
+ /* Happens for old files that don't have versioning applied yet. */
+ return;
}
- /* Collection is already where we want it to be in the scene tree
- * but we want to swap it in the layer tree still */
- if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) {
- LayerCollection *lc_swap = lc_dst->layer_collections.last;
- layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src);
-
- if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
- BKE_collection_unlink(view_layer, lc_swap);
- }
- return true;
- }
- else {
- LayerCollection *lc_temp;
- is_directly_linked = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
-
- if (!is_directly_linked) {
- /* lc_src will be invalid after BKE_collection_move_into!
- * so we swap it with lc_temp to preserve its settings */
- lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
- layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
- }
+ /* Free cache. */
+ MEM_SAFE_FREE(view_layer->object_bases_array);
- if (!BKE_collection_move_into(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) {
- if (!is_directly_linked) {
- /* Swap back and remove */
- layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src);
- BKE_collection_unlink(view_layer, lc_temp);
- }
- return false;
- }
+ /* Create object to base hash if it does not exist yet. */
+ if (!view_layer->object_bases_hash) {
+ view_layer_bases_hash_create(view_layer);
}
- LayerCollection *lc_new = BLI_findptr(
- &lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection));
- BLI_assert(lc_new);
- layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_new, lc_src);
-
- /* If it's directly linked, unlink it after the swap */
- if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
- BKE_collection_unlink(view_layer, lc_new);
+ /* Clear visible and selectable flags to be reset. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED | BASE_VISIBLE_VIEWPORT | BASE_VISIBLE_RENDER);
}
- return true;
-}
+ /* Generate new layer connections and object bases when collections changed. */
+ CollectionChild child = {NULL, NULL, scene->master_collection};
+ const ListBase collections = {&child, &child};
+ ListBase new_object_bases = {NULL, NULL};
-/**
- * Move \a lc_src above \a lc_dst. Both have to be stored in \a view_layer.
- * If \a lc_src is directly linked to the ViewLayer it's unlinked
- */
-bool BKE_layer_collection_move_above(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
-{
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src);
- const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
- const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1;
+ const int parent_exclude = 0, parent_restrict = 0;
+ layer_collection_sync(view_layer, &collections, &view_layer->layer_collections, &new_object_bases, parent_exclude, parent_restrict);
- if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
- return false;
- }
+ /* Any remaning object bases are to be removed. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (view_layer->basact == base) {
+ view_layer->basact = NULL;
+ }
- /* Collection is already where we wanted it to be */
- if (lc_dst->prev == lc_src) {
- return false;
+ BLI_ghash_remove(view_layer->object_bases_hash, base->object, NULL, NULL);
}
- /* Collection is already where we want it to be in the scene tree
- * but we want to swap it in the layer tree still */
- if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) {
- LayerCollection *lc_swap = lc_dst->prev;
- layer_collection_swap(view_layer, NULL, NULL, lc_dst->prev, lc_src);
-
- if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
- BKE_collection_unlink(view_layer, lc_swap);
- }
- return true;
- }
- /* We don't allow to move above/below a directly linked collection
- * unless the source collection is also directly linked */
- else if (is_directly_linked_dst) {
- /* Both directly linked to the ViewLayer, just need to swap */
- if (is_directly_linked_src) {
- BLI_remlink(&view_layer->layer_collections, lc_src);
- BLI_insertlinkbefore(&view_layer->layer_collections, lc_dst, lc_src);
- return true;
- }
- else {
- return false;
- }
- }
- else {
- LayerCollection *lc_temp;
+ BLI_freelistN(&view_layer->object_bases);
+ view_layer->object_bases = new_object_bases;
- if (!is_directly_linked_src) {
- /* lc_src will be invalid after BKE_collection_move_into!
- * so we swap it with lc_temp to preserve its settings */
- lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
- layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
- }
+ /* Always set a valid active collection. */
+ LayerCollection *active = view_layer->active_collection;
- if (!BKE_collection_move_above(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) {
- if (!is_directly_linked_src) {
- /* Swap back and remove */
- layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src);
- BKE_collection_unlink(view_layer, lc_temp);
- }
- return false;
- }
+ if (active && (active->flag & LAYER_COLLECTION_EXCLUDE)) {
+ BKE_layer_collection_activate_parent(view_layer, active);
}
-
- LayerCollection *lc_new = lc_dst->prev;
- BLI_assert(lc_new);
- layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src);
-
- /* If it's directly linked, unlink it after the swap */
- if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
- BKE_collection_unlink(view_layer, lc_new);
+ else if (active == NULL) {
+ view_layer->active_collection = view_layer->layer_collections.first;
}
-
- return true;
}
-/**
- * Move \a lc_src below \a lc_dst. Both have to be stored in \a view_layer.
- * If \a lc_src is directly linked to the ViewLayer it's unlinked
- */
-bool BKE_layer_collection_move_below(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src)
+void BKE_scene_collection_sync(const Scene *scene)
{
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src);
- const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1;
- const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1;
-
- if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) {
- return false;
- }
-
- /* Collection is already where we wanted it to be */
- if (lc_dst->next == lc_src) {
- return false;
- }
-
- /* Collection is already where we want it to be in the scene tree
- * but we want to swap it in the layer tree still */
- if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) {
- LayerCollection *lc_swap = lc_dst->next;
- layer_collection_swap(view_layer, NULL, NULL, lc_dst->next, lc_src);
-
- if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) {
- BKE_collection_unlink(view_layer, lc_swap);
- }
- return true;
- }
- /* We don't allow to move above/below a directly linked collection
- * unless the source collection is also directly linked */
- else if (is_directly_linked_dst) {
- /* Both directly linked to the ViewLayer, just need to swap */
- if (is_directly_linked_src) {
- BLI_remlink(&view_layer->layer_collections, lc_src);
- BLI_insertlinkafter(&view_layer->layer_collections, lc_dst, lc_src);
- return true;
- }
- else {
- return false;
- }
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ BKE_layer_collection_sync(scene, view_layer);
}
- else {
- LayerCollection *lc_temp;
-
- if (!is_directly_linked_src) {
- /* lc_src will be invalid after BKE_collection_move_into!
- * so we swap it with lc_temp to preserve its settings */
- lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection);
- layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src);
- }
+}
- if (!BKE_collection_move_below(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) {
- if (!is_directly_linked_src) {
- /* Swap back and remove */
- layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src);
- BKE_collection_unlink(view_layer, lc_temp);
- }
- return false;
- }
- }
+void BKE_main_collection_sync(const Main *bmain)
+{
+ /* TODO: if a single collection changed, figure out which
+ * scenes it belongs to and only update those. */
- LayerCollection *lc_new = lc_dst->next;
- BLI_assert(lc_new);
- layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src);
+ /* TODO: optimize for file load so only linked collections get checked? */
- /* If it's directly linked, unlink it after the swap */
- if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) {
- BKE_collection_unlink(view_layer, lc_new);
+ for (const Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ BKE_scene_collection_sync(scene);
}
-
- return true;
}
-static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, const SceneCollection *sc)
+void BKE_main_collection_sync_remap(const Main *bmain)
{
- if (lc->scene_collection == sc) {
- ListBase collections = {NULL};
- BLI_movelisttolist(&collections, &lc->layer_collections);
+ /* On remapping of object or collection pointers free caches. */
+ /* TODO: try to make this faster */
- for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
- LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection));
- if (lc_nested) {
- BLI_remlink(&collections, lc_nested);
- BLI_addtail(&lc->layer_collections, lc_nested);
- }
- else {
- layer_collection_add(view_layer, lc, sc_nested);
- }
- }
+ for (const Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ MEM_SAFE_FREE(view_layer->object_bases_array);
- for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) {
- layer_collection_free(view_layer, lc_nested);
+ if (view_layer->object_bases_hash) {
+ BLI_ghash_free(view_layer->object_bases_hash, NULL, NULL);
+ view_layer->object_bases_hash = NULL;
+ }
}
- BLI_freelistN(&collections);
-
- BLI_assert(BLI_listbase_count(&lc->layer_collections) ==
- BLI_listbase_count(&sc->scene_collections));
-
- return true;
}
- for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) {
- if (layer_collection_resync(view_layer, lc_nested, sc)) {
- return true;
- }
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ BKE_collection_object_cache_free(collection);
}
- return false;
-}
-
-/**
- * Update the scene layers so that any LayerCollection that points
- * to \a sc is re-synced again
- */
-void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
-{
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- layer_collection_resync(view_layer, lc, sc);
- }
- }
+ BKE_main_collection_sync(bmain);
}
/* ---------------------------------------------------------------------- */
@@ -1102,161 +727,69 @@ void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
* It also select the objects that are in nested collections.
* \note Recursive
*/
-void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection)
+bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection *lc, bool deselect)
{
- if ((layer_collection->flag & COLLECTION_DISABLED) ||
- ((layer_collection->flag & COLLECTION_SELECTABLE) == 0))
- {
- return;
- }
-
- for (LinkData *link = layer_collection->object_bases.first; link; link = link->next) {
- Base *base = link->data;
- if (base->flag & BASE_SELECTABLED) {
- base->flag |= BASE_SELECTED;
- }
- }
-
- for (LayerCollection *iter = layer_collection->layer_collections.first; iter; iter = iter->next) {
- BKE_layer_collection_objects_select(iter);
- }
-}
-
-/* ---------------------------------------------------------------------- */
-
-/**
- * Link a collection to a renderlayer
- * The collection needs to be created separately
- */
-LayerCollection *BKE_collection_link(ViewLayer *view_layer, SceneCollection *sc)
-{
- LayerCollection *lc = layer_collection_add(view_layer, NULL, sc);
- view_layer->active_collection = BKE_layer_collection_findindex(view_layer, lc);
- return lc;
-}
-
-/**
- * Unlink a collection base from a renderlayer
- * The corresponding collection is not removed from the master collection
- */
-void BKE_collection_unlink(ViewLayer *view_layer, LayerCollection *lc)
-{
- BKE_layer_collection_free(view_layer, lc);
- BLI_remlink(&view_layer->layer_collections, lc);
- MEM_freeN(lc);
- view_layer->active_collection = 0;
-}
-
-/**
- * Recursively enable nested collections
- */
-static void layer_collection_enable(ViewLayer *view_layer, LayerCollection *lc)
-{
- layer_collection_objects_populate(view_layer, lc, &lc->scene_collection->objects);
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- layer_collection_enable(view_layer, nlc);
- }
-}
-
-/**
- * Enable collection
- * Add its objects bases to ViewLayer
- *
- * Only around for doversion.
- */
-void BKE_collection_enable(ViewLayer *view_layer, LayerCollection *lc)
-{
- if ((lc->flag & COLLECTION_DISABLED) == 0) {
- return;
+ if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) {
+ return false;
}
- lc->flag &= ~COLLECTION_DISABLED;
- layer_collection_enable(view_layer, lc);
-}
-
-static void layer_collection_object_add(ViewLayer *view_layer, LayerCollection *lc, Object *ob)
-{
- Base *base = object_base_add(view_layer, ob);
-
- /* Only add an object once. */
- if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
- return;
- }
+ bool changed = false;
- bool is_visible = ((lc->flag & COLLECTION_VIEWPORT) != 0) && ((lc->flag & COLLECTION_DISABLED) == 0);
- bool is_selectable = is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+ if (!(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ for (CollectionObject *cob = lc->collection->gobject.first; cob; cob = cob->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
- if (is_visible) {
- base->flag |= BASE_VISIBLED;
+ if (base) {
+ if (deselect) {
+ if (base->flag & BASE_SELECTED) {
+ base->flag &= ~BASE_SELECTED;
+ changed = true;
+ }
+ }
+ else {
+ if ((base->flag & BASE_SELECTABLED) && !(base->flag & BASE_SELECTED)) {
+ base->flag |= BASE_SELECTED;
+ changed = true;
+ }
+ }
+ }
+ }
}
- if (is_selectable) {
- base->flag |= BASE_SELECTABLED;
+ for (LayerCollection *iter = lc->layer_collections.first; iter; iter = iter->next) {
+ changed |= BKE_layer_collection_objects_select(view_layer, iter, deselect);
}
- BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
+ return changed;
}
-static void layer_collection_object_remove(ViewLayer *view_layer, LayerCollection *lc, Object *ob)
-{
- Base *base;
- base = BKE_view_layer_base_find(view_layer, ob);
-
- LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
- BLI_remlink(&lc->object_bases, link);
- MEM_freeN(link);
-
- view_layer_object_base_unref(view_layer, base);
-}
+/* ---------------------------------------------------------------------- */
-static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects)
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const Collection *collection)
{
- for (LinkData *link = objects->first; link; link = link->next) {
- layer_collection_object_add(view_layer, lc, link->data);
+ if (lc->collection == collection) {
+ return lc;
}
-}
-static void layer_collection_populate(ViewLayer *view_layer, LayerCollection *lc, SceneCollection *sc)
-{
- layer_collection_objects_populate(view_layer, lc, &sc->objects);
-
- for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- layer_collection_add(view_layer, lc, nsc);
- }
-}
-
-static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc)
-{
- LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
-
- lc->scene_collection = sc;
- lc->flag = COLLECTION_SELECTABLE | COLLECTION_VIEWPORT | COLLECTION_RENDER;
-
- if (parent != NULL) {
- BLI_addtail(&parent->layer_collections, lc);
- }
- else {
- BLI_addtail(&view_layer->layer_collections, lc);
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(nlc, collection);
+ if (found) {
+ return found;
+ }
}
-
- layer_collection_populate(view_layer, lc, sc);
-
- return lc;
+ return NULL;
}
-/* ---------------------------------------------------------------------- */
-
/**
- * Return the first matching LayerCollection in the ViewLayer for the SceneCollection.
+ * Return the first matching LayerCollection in the ViewLayer for the Collection.
*/
-LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
+LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const Collection *collection)
{
for (LayerCollection *layer_collection = view_layer->layer_collections.first;
layer_collection != NULL;
layer_collection = layer_collection->next)
{
- LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, scene_collection);
+ LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, collection);
if (found != NULL) {
return found;
@@ -1268,9 +801,9 @@ LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *vie
/**
* See if view layer has the scene collection linked directly, or indirectly (nested)
*/
-bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
+bool BKE_view_layer_has_collection(ViewLayer *view_layer, const Collection *collection)
{
- return BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection) != NULL;
+ return BKE_layer_collection_first_from_scene_collection(view_layer, collection) != NULL;
}
/**
@@ -1287,70 +820,6 @@ bool BKE_scene_has_object(Scene *scene, Object *ob)
return false;
}
-
-/* ---------------------------------------------------------------------- */
-/* Syncing */
-
-static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
-{
- if (lc->scene_collection == sc) {
- return lc;
- }
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
- if (found) {
- return found;
- }
- }
- return NULL;
-}
-
-/**
- * Add a new LayerCollection for all the ViewLayers that have sc_parent
- */
-void BKE_layer_sync_new_scene_collection(ID *owner_id, const SceneCollection *sc_parent, SceneCollection *sc)
-{
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
- if (lc_parent) {
- layer_collection_add(view_layer, lc_parent, sc);
- }
- }
- }
-}
-
-/**
- * Add a corresponding ObjectBase to all the equivalent LayerCollection
- */
-void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object *ob)
-{
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
- if (found) {
- layer_collection_object_add(view_layer, found, ob);
- }
- }
- }
-}
-
-/**
- * Remove the equivalent object base to all layers that have this collection
- */
-void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob)
-{
- for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
- for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
- if (found) {
- layer_collection_object_remove(view_layer, found, ob);
- }
- }
- }
-}
-
/* ---------------------------------------------------------------------- */
/* Override */
@@ -1677,93 +1146,28 @@ void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *UNUSED(iter))
/* Evaluation */
-static void layer_eval_layer_collection_pre(Depsgraph *depsgraph, ID *UNUSED(owner_id), ViewLayer *view_layer)
+void BKE_layer_eval_view_layer(struct Depsgraph *depsgraph,
+ struct Scene *UNUSED(scene),
+ ViewLayer *view_layer)
{
DEG_debug_print_eval(depsgraph, __func__, view_layer->name, view_layer);
- //Scene *scene = (GS(owner_id->name) == ID_SCE) ? (Scene *)owner_id : NULL;
- for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
- base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED);
- }
+ /* Set visibility based on depsgraph mode. */
+ const eEvaluationMode mode = DEG_get_mode(depsgraph);
+ const int base_flag = (mode == DAG_EVAL_VIEWPORT) ? BASE_VISIBLE_VIEWPORT : BASE_VISIBLE_RENDER;
- /* TODO(sergey): Is it always required? */
- view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
-}
-
-static const char *collection_type_lookup[] =
-{
- "None", /* COLLECTION_TYPE_NONE */
- "Group Internal", /* COLLECTION_TYPE_GROUP_INTERNAL */
-};
-
-/**
- * \note We can't use layer_collection->flag because of 3 level nesting (where parent is visible, but not grand-parent)
- * So layer_collection->flag_evaluated is expected to be up to date with layer_collection->flag.
- */
-static bool layer_collection_visible_get(Depsgraph *depsgraph, LayerCollection *layer_collection)
-{
- if (layer_collection->flag_evaluated & COLLECTION_DISABLED) {
- return false;
- }
-
- if (DEG_get_mode(depsgraph) == DAG_EVAL_VIEWPORT) {
- return (layer_collection->flag_evaluated & COLLECTION_VIEWPORT) != 0;
- }
- else {
- return (layer_collection->flag_evaluated & COLLECTION_RENDER) != 0;
- }
-}
-
-static void layer_eval_layer_collection(Depsgraph *depsgraph,
- LayerCollection *layer_collection,
- LayerCollection *parent_layer_collection)
-{
- DEG_debug_print_eval_parent_typed(
- depsgraph,
- __func__,
- layer_collection->scene_collection->name,
- layer_collection->scene_collection,
- collection_type_lookup[layer_collection->scene_collection->type],
- "parent",
- (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE",
- (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL,
- (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : "");
- BLI_assert(layer_collection != parent_layer_collection);
-
- /* visibility */
- layer_collection->flag_evaluated = layer_collection->flag;
-
- if (parent_layer_collection != NULL) {
- if (layer_collection_visible_get(depsgraph, parent_layer_collection) == false) {
- layer_collection->flag_evaluated |= COLLECTION_DISABLED;
- }
-
- if ((parent_layer_collection->flag_evaluated & COLLECTION_DISABLED) ||
- (parent_layer_collection->flag_evaluated & COLLECTION_SELECTABLE) == 0)
- {
- layer_collection->flag_evaluated &= ~COLLECTION_SELECTABLE;
- }
- }
-
- const bool is_visible = layer_collection_visible_get(depsgraph, layer_collection);
- const bool is_selectable = is_visible && ((layer_collection->flag_evaluated & COLLECTION_SELECTABLE) != 0);
-
- for (LinkData *link = layer_collection->object_bases.first; link != NULL; link = link->next) {
- Base *base = link->data;
-
- if (is_visible) {
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ if (base->flag & base_flag) {
base->flag |= BASE_VISIBLED;
}
-
- if (is_selectable) {
- base->flag |= BASE_SELECTABLED;
+ else {
+ base->flag &= ~BASE_VISIBLED;
}
}
-}
-static void layer_eval_layer_collection_post(Depsgraph *depsgraph, ViewLayer *view_layer)
-{
- DEG_debug_print_eval(depsgraph, __func__, view_layer->name, view_layer);
+ /* TODO(sergey): Is it always required? */
+ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
+
/* Create array of bases, for fast index-based lookup. */
const int num_object_bases = BLI_listbase_count(&view_layer->object_bases);
MEM_SAFE_FREE(view_layer->object_bases_array);
@@ -1780,42 +1184,12 @@ static void layer_eval_layer_collection_post(Depsgraph *depsgraph, ViewLayer *vi
}
}
-static void layer_eval_collections_recurse(Depsgraph *depsgraph,
- ListBase *layer_collections,
- LayerCollection *parent_layer_collection)
-{
- for (LayerCollection *layer_collection = layer_collections->first;
- layer_collection != NULL;
- layer_collection = layer_collection->next)
- {
- layer_eval_layer_collection(depsgraph,
- layer_collection,
- parent_layer_collection);
- layer_eval_collections_recurse(depsgraph,
- &layer_collection->layer_collections,
- layer_collection);
- }
-}
-
-void BKE_layer_eval_view_layer(struct Depsgraph *depsgraph,
- struct ID *owner_id,
- ViewLayer *view_layer)
-{
- layer_eval_layer_collection_pre(depsgraph, owner_id, view_layer);
- layer_eval_collections_recurse(depsgraph,
- &view_layer->layer_collections,
- NULL);
- layer_eval_layer_collection_post(depsgraph, view_layer);
-}
-
void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph,
- struct ID *owner_id,
+ struct Scene *scene,
int view_layer_index)
{
- BLI_assert(GS(owner_id->name) == ID_SCE);
BLI_assert(view_layer_index >= 0);
- Scene *scene = (Scene *)owner_id;
ViewLayer *view_layer = BLI_findlink(&scene->view_layers, view_layer_index);
BLI_assert(view_layer != NULL);
- BKE_layer_eval_view_layer(depsgraph, owner_id, view_layer);
+ BKE_layer_eval_view_layer(depsgraph, scene, view_layer);
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 883f0342159..3926d2055f0 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -91,11 +91,11 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_font.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_gpencil.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
@@ -437,7 +437,7 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local);
return true;
case ID_GR:
- if (!test) BKE_group_make_local(bmain, (Group *)id, lib_local);
+ if (!test) BKE_collection_make_local(bmain, (Collection *)id, lib_local);
return true;
case ID_AR:
if (!test) BKE_armature_make_local(bmain, (bArmature *)id, lib_local);
@@ -615,7 +615,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag);
break;
case ID_GR:
- BKE_group_copy_data(bmain, (Group *)*r_newid, (Group *)id, flag);
+ BKE_collection_copy_data(bmain, (Collection *)*r_newid, (Collection *)id, flag);
break;
case ID_AR:
BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag);
@@ -729,7 +729,7 @@ void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
CASE_SWAP(ID_TXT, Text);
CASE_SWAP(ID_SPK, Speaker);
CASE_SWAP(ID_SO, bSound);
- CASE_SWAP(ID_GR, Group);
+ CASE_SWAP(ID_GR, Collection);
CASE_SWAP(ID_AR, bArmature);
CASE_SWAP(ID_AC, bAction);
CASE_SWAP(ID_NT, bNodeTree);
@@ -935,7 +935,7 @@ ListBase *which_libbase(Main *mainlib, short type)
case ID_SO:
return &(mainlib->sound);
case ID_GR:
- return &(mainlib->group);
+ return &(mainlib->collection);
case ID_AR:
return &(mainlib->armature);
case ID_AC:
@@ -1096,7 +1096,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_TXT] = &(main->text);
lb[INDEX_ID_SO] = &(main->sound);
- lb[INDEX_ID_GR] = &(main->group);
+ lb[INDEX_ID_GR] = &(main->collection);
lb[INDEX_ID_PAL] = &(main->palettes);
lb[INDEX_ID_PC] = &(main->paintcurves);
lb[INDEX_ID_BR] = &(main->brush);
@@ -1165,7 +1165,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
CASE_RETURN(ID_SPK, Speaker);
CASE_RETURN(ID_LP, LightProbe);
CASE_RETURN(ID_SO, bSound);
- CASE_RETURN(ID_GR, Group);
+ CASE_RETURN(ID_GR, Collection);
CASE_RETURN(ID_AR, bArmature);
CASE_RETURN(ID_AC, bAction);
CASE_RETURN(ID_NT, bNodeTree);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index efc550ac64c..dbfe619153d 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -72,7 +72,6 @@
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -287,6 +286,16 @@ static void library_foreach_bone(LibraryForeachIDData *data, Bone *bone)
FOREACH_FINALIZE_VOID;
}
+static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ FOREACH_CALLBACK_INVOKE(data, lc->collection, IDWALK_CB_NOP);
+ library_foreach_layer_collection(data, &lc->layer_collections);
+ }
+
+ FOREACH_FINALIZE_VOID;
+}
+
static void library_foreach_ID_as_subdata_link(
ID **id_pp, LibraryIDLinkCallback callback, void *user_data, int flag, LibraryForeachIDData *data)
{
@@ -409,20 +418,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
- {
- for (LinkData *link = sc->objects.first; link; link = link->next) {
- CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
- }
+ for (CollectionObject *cob = scene->master_collection->gobject.first; cob; cob = cob->next) {
+ CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
+ }
+ for (CollectionChild *child = scene->master_collection->children.first; child; child = child->next) {
+ CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
}
- FOREACH_SCENE_COLLECTION_END;
ViewLayer *view_layer;
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ CALLBACK_INVOKE(base->object, IDWALK_CB_NOP);
}
+ library_foreach_layer_collection(&data, &view_layer->layer_collections);
+
for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
if (fmc->script) {
CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
@@ -702,12 +712,13 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
case ID_GR:
{
- Group *group = (Group *) id;
- FOREACH_GROUP_BASE_BEGIN(group, base)
- {
- CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE);
+ Collection *collection = (Collection *) id;
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ CALLBACK_INVOKE(cob->ob, IDWALK_CB_USER);
+ }
+ for (CollectionChild *child = collection->children.first; child; child = child->next) {
+ CALLBACK_INVOKE(child->collection, IDWALK_CB_USER);
}
- FOREACH_GROUP_BASE_END
break;
}
@@ -1048,7 +1059,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
case ID_SPK:
return ELEM(id_type_used, ID_SO);
case ID_GR:
- return ELEM(id_type_used, ID_OB);
+ return ELEM(id_type_used, ID_OB, ID_GR);
case ID_NT:
/* Could be the following, but node.id has no type restriction... */
#if 0
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 983f6781572..cf2a001daaa 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -77,7 +77,6 @@
#include "BKE_curve.h"
#include "BKE_fcurve.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_gpencil.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
@@ -271,25 +270,27 @@ static void libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data->skipped_refcounted++;
}
else {
- BKE_collections_object_remove(r_id_remap_data->bmain, &sce->id, ob, false);
+ /* Remove object from all collections in the scene. free_use is false
+ * to avoid recursively calling object free again. */
+ BKE_scene_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
}
}
-static void libblock_remap_data_preprocess_group_unlink(
+static void libblock_remap_data_preprocess_collection_unlink(
IDRemap *r_id_remap_data, Object *ob, const bool skip_indirect, const bool is_indirect)
{
Main *bmain = r_id_remap_data->bmain;
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- if (BKE_group_object_exists(group, ob)) {
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ if (!BKE_collection_is_in_scene(collection) && BKE_collection_has_object(collection, ob)) {
if (skip_indirect && is_indirect) {
r_id_remap_data->skipped_indirect++;
r_id_remap_data->skipped_refcounted++;
}
else {
- BKE_collections_object_remove(bmain, &group->id, ob, false);
+ BKE_collection_object_remove(bmain, collection, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
@@ -311,12 +312,14 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
+ /* TODO: how is it valid to iterator over a scene while
+ * removing objects from it? can't this crash? */
/* ... everything from scene. */
FOREACH_SCENE_OBJECT_BEGIN(sce, ob_iter)
{
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
- libblock_remap_data_preprocess_group_unlink(
+ libblock_remap_data_preprocess_collection_unlink(
r_id_remap_data, ob_iter, skip_indirect, is_indirect);
}
FOREACH_SCENE_OBJECT_END;
@@ -326,7 +329,7 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
Object *old_ob = (Object *)r_id_remap_data->old_id;
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
- libblock_remap_data_preprocess_group_unlink(
+ libblock_remap_data_preprocess_collection_unlink(
r_id_remap_data, old_ob, skip_indirect, is_indirect);
}
@@ -360,23 +363,16 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *old_ob, Object *new_ob)
{
- if (old_ob->flag & OB_FROMGROUP) {
- /* Note that for Scene's BaseObject->flag, either we:
- * - unlinked old_ob (i.e. new_ob is NULL), in which case scenes' bases have been removed already.
- * - remapped old_ob by new_ob, in which case scenes' bases are still valid as is.
- * So in any case, no need to update them here. */
- if (BKE_group_object_find(NULL, old_ob) == NULL) {
- old_ob->flag &= ~OB_FROMGROUP;
- }
- if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
- for (Group *group = bmain->group.first; group; group = group->id.next) {
- BKE_group_object_unlink(group, NULL);
- }
- }
- else {
- new_ob->flag |= OB_FROMGROUP;
- }
+ if (new_ob == NULL) {
+ /* In case we unlinked old_ob (new_ob is NULL), the object has already
+ * been removed from the scenes and their collections. We still have
+ * to remove the NULL children from collections not used in any scene. */
+ BKE_collections_object_remove_nulls(bmain);
}
+ else {
+ BKE_main_collection_sync_remap(bmain);
+ }
+
if (old_ob->type == OB_MBALL) {
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) {
@@ -386,27 +382,20 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *o
}
}
-static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmain), Scene *sce, ID *old_id)
+static void libblock_remap_data_postprocess_collection_update(Main *bmain, Collection *old_collection, Collection *new_collection)
{
- /* Note that here we assume no object has no base (i.e. all objects are assumed instanced
- * in one scene...). */
- FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
- {
- if (ob->flag & OB_FROMGROUP) {
- Group *grp = BKE_group_object_find(NULL, ob);
-
- /* Unlinked group (old_id) is still in bmain... */
- if (grp && (&grp->id == old_id || grp->id.us == 0)) {
- grp = BKE_group_object_find(grp, ob);
- }
- if (!grp) {
- ob->flag &= ~OB_FROMGROUP;
- }
- }
+ if (new_collection == NULL) {
+ /* In case we unlinked old_collection (new_collection is NULL), we need
+ * to remove any collection children that have been set to NULL in the
+ * because of pointer replacement. */
+ BKE_collections_child_remove_nulls(bmain, old_collection);
+ }
+ else {
+ BKE_main_collection_sync_remap(bmain);
}
- FOREACH_SCENE_OBJECT_END;
}
+
static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
{
if (ob->data == new_id) {
@@ -588,11 +577,7 @@ void BKE_libblock_remap_locked(
libblock_remap_data_postprocess_object_update(bmain, (Object *)old_id, (Object *)new_id);
break;
case ID_GR:
- if (!new_id) { /* Only affects us in case group was unlinked. */
- for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
- libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, old_id);
- }
- }
+ libblock_remap_data_postprocess_collection_update(bmain, (Collection *)old_id, (Collection *)new_id);
break;
case ID_ME:
case ID_CU:
@@ -689,8 +674,6 @@ void BKE_libblock_relink_ex(
switch (GS(id->name)) {
case ID_SCE:
{
- Scene *sce = (Scene *)id;
-
if (old_id) {
switch (GS(old_id->name)) {
case ID_OB:
@@ -699,21 +682,19 @@ void BKE_libblock_relink_ex(
break;
}
case ID_GR:
- if (!new_id) { /* Only affects us in case group was unlinked. */
- libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, old_id);
- }
+ libblock_remap_data_postprocess_collection_update(bmain, (Collection *)old_id, (Collection *)new_id);
break;
default:
break;
}
}
else {
- /* No choice but to check whole objects/groups. */
+ /* No choice but to check whole objects/collections. */
for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
libblock_remap_data_postprocess_object_update(bmain, ob, NULL);
}
- for (Group *grp = bmain->group.first; grp; grp = grp->id.next) {
- libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, NULL);
+ for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
+ libblock_remap_data_postprocess_collection_update(bmain, collection, NULL);
}
}
break;
@@ -843,7 +824,7 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
BKE_sound_free((bSound *)id);
break;
case ID_GR:
- BKE_group_free((Group *)id);
+ BKE_collection_free((Collection *)id);
break;
case ID_AR:
BKE_armature_free((bArmature *)id);
@@ -1038,8 +1019,8 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
id_us_min(id);
- /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding groups when deleting an object.
- * Since only 'user_one' usage of objects is groups, and only 'real user' usage of objects is scenes,
+ /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding collections when deleting an object.
+ * Since only 'user_one' usage of objects is collections, and only 'real user' usage of objects is scenes,
* removing that 'user_one' tag when there is no more real (scene) users of an object ensures it gets
* fully unlinked.
* But only for local objects, not linked ones!
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index bced9a1e019..1e6d3041f3f 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -80,12 +80,12 @@
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_anim.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
#include "BKE_fcurve.h"
-#include "BKE_group.h"
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
@@ -719,7 +719,7 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob = BKE_libblock_alloc(bmain, ID_OB, name, 0);
- /* We increase object user count when linking to SceneCollections. */
+ /* We increase object user count when linking to Collections. */
id_us_min(&ob->id);
/* default object vars */
@@ -746,12 +746,12 @@ static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, c
/**
* General add: to scene, with layer from area and default name
*
- * Object is added to the active SceneCollection.
+ * Object is added to the active Collection.
* If there is no linked collection to the active ViewLayer we create a new one.
*/
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
- Main *bmain, Scene *scene, ViewLayer *view_layer,
+ Main *bmain, Scene *UNUSED(scene), ViewLayer *view_layer,
int type, const char *name)
{
Object *ob;
@@ -760,8 +760,8 @@ Object *BKE_object_add(
ob = object_add_common(bmain, view_layer, type, name);
- layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
- BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
+ layer_collection = BKE_layer_collection_get_active(view_layer);
+ BKE_collection_object_add(bmain, layer_collection->collection, ob);
base = BKE_view_layer_base_find(view_layer, ob);
BKE_view_layer_base_select(view_layer, base);
@@ -782,7 +782,7 @@ Object *BKE_object_add_from(
Base *base;
ob = object_add_common(bmain, view_layer, type, name);
- BKE_collection_object_add_from(scene, ob_src, ob);
+ BKE_collection_object_add_from(bmain, scene, ob_src, ob);
base = BKE_view_layer_base_find(view_layer, ob);
BKE_view_layer_base_select(view_layer, base);
@@ -1157,7 +1157,6 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
if (ob_src->iuser) ob_dst->iuser = MEM_dupallocN(ob_src->iuser);
if (ob_src->bb) ob_dst->bb = MEM_dupallocN(ob_src->bb);
- ob_dst->flag &= ~OB_FROMGROUP;
BLI_listbase_clear(&ob_dst->modifiers);
@@ -1344,9 +1343,9 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
/* proxy rule: lib_object->proxy_from == the one we borrow from, set temporally while object_update */
/* local_object->proxy == pointer to library object, saved in files and read */
-/* local_object->proxy_group == pointer to group dupli-object, saved in files and read */
+/* local_object->proxy_group == pointer to collection dupli-object, saved in files and read */
-void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
+void BKE_object_make_proxy(Object *ob, Object *target, Object *cob)
{
/* paranoia checks */
if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
@@ -1355,24 +1354,24 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
}
ob->proxy = target;
- ob->proxy_group = gob;
+ ob->proxy_group = cob;
id_lib_extern(&target->id);
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
DEG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* copy transform
- * - gob means this proxy comes from a group, just apply the matrix
+ * - cob means this proxy comes from a collection, just apply the matrix
* so the object wont move from its dupli-transform.
*
- * - no gob means this is being made from a linked object,
+ * - no cob means this is being made from a linked object,
* this is closer to making a copy of the object - in-place. */
- if (gob) {
+ if (cob) {
ob->rotmode = target->rotmode;
- mul_m4_m4m4(ob->obmat, gob->obmat, target->obmat);
- if (gob->dup_group) { /* should always be true */
+ mul_m4_m4m4(ob->obmat, cob->obmat, target->obmat);
+ if (cob->dup_group) { /* should always be true */
float tvec[3];
- mul_v3_mat3_m4v3(tvec, ob->obmat, gob->dup_group->dupli_ofs);
+ mul_v3_mat3_m4v3(tvec, ob->obmat, cob->dup_group->dupli_ofs);
sub_v3_v3(ob->obmat[3], tvec);
}
BKE_object_apply_mat4(ob, ob->obmat, false, true);
@@ -2624,13 +2623,13 @@ static void object_handle_update_proxy(Depsgraph *depsgraph,
Object *object,
const bool do_proxy_update)
{
- /* The case when this is a group proxy, object_update is called in group.c */
+ /* The case when this is a collection proxy, object_update is called in collection.c */
if (object->proxy == NULL) {
return;
}
/* set pointer in library proxy target, for copying, but restore it */
object->proxy->proxy_from = object;
- // printf("set proxy pointer for later group stuff %s\n", ob->id.name);
+ // printf("set proxy pointer for later collection stuff %s\n", ob->id.name);
/* the no-group proxy case, we call update */
if (object->proxy_group == NULL) {
@@ -3410,22 +3409,22 @@ LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSe
/**
* return all groups this object is apart of, caller must free.
*/
-struct LinkNode *BKE_object_groups(Object *ob)
+struct LinkNode *BKE_object_groups(Main *bmain, Object *ob)
{
- LinkNode *group_linknode = NULL;
- Group *group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- BLI_linklist_prepend(&group_linknode, group);
+ LinkNode *collection_linknode = NULL;
+ Collection *collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ BLI_linklist_prepend(&collection_linknode, collection);
}
- return group_linknode;
+ return collection_linknode;
}
-void BKE_object_groups_clear(Object *ob)
+void BKE_object_groups_clear(Main *bmain, Object *ob)
{
- Group *group = NULL;
- while ((group = BKE_group_object_find(group, ob))) {
- BKE_group_object_unlink(group, ob);
+ Collection *collection = NULL;
+ while ((collection = BKE_collection_object_find(bmain, collection, ob))) {
+ BKE_collection_object_remove(bmain, collection, ob, false);
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index d99a1ba8c0b..5e42cdb6b14 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -48,10 +48,10 @@
#include "DNA_vfont_types.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
#include "BKE_font.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
@@ -74,7 +74,7 @@ typedef struct DupliContext {
Depsgraph *depsgraph;
bool do_update;
bool animated;
- Group *group; /* XXX child objects are selected from this group if set, could be nicer */
+ Collection *collection; /* XXX child objects are selected from this group if set, could be nicer */
Object *obedit; /* Only to check if the object is in edit-mode. */
Scene *scene;
@@ -107,7 +107,7 @@ static void init_context(DupliContext *r_ctx, Depsgraph *depsgraph, Scene *scene
/* don't allow BKE_object_handle_update for viewport during render, can crash */
r_ctx->do_update = update && !(G.is_rendering && DEG_get_mode(depsgraph) != DAG_EVAL_RENDER);
r_ctx->animated = false;
- r_ctx->group = NULL;
+ r_ctx->collection = NULL;
r_ctx->object = ob;
r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
@@ -130,8 +130,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj
r_ctx->animated |= animated; /* object animation makes all children animated */
/* XXX annoying, previously was done by passing an ID* argument, this at least is more explicit */
- if (ctx->gen->type == OB_DUPLIGROUP)
- r_ctx->group = ctx->object->dup_group;
+ if (ctx->gen->type == OB_DUPLICOLLECTION)
+ r_ctx->collection = ctx->object->dup_group;
r_ctx->object = ob;
if (mat)
@@ -210,7 +210,7 @@ static DupliObject *make_dupli(const DupliContext *ctx,
*/
static void make_recursive_duplis(const DupliContext *ctx, Object *ob, float space_mat[4][4], int index, bool animated)
{
- /* simple preventing of too deep nested groups with MAX_DUPLI_RECUR */
+ /* simple preventing of too deep nested collections with MAX_DUPLI_RECUR */
if (ctx->level < MAX_DUPLI_RECUR) {
DupliContext rctx;
copy_dupli_context(&rctx, ctx, ob, space_mat, index, animated);
@@ -235,19 +235,19 @@ static bool is_child(const Object *ob, const Object *parent)
return false;
}
-/* create duplis from every child in scene or group */
+/* create duplis from every child in scene or collection */
static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChildDuplisFunc make_child_duplis_cb)
{
Object *parent = ctx->object;
- if (ctx->group) {
- int groupid = 0;
- FOREACH_GROUP_BASE_BEGIN(ctx->group, base)
+ if (ctx->collection) {
+ int collectionid = 0;
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(ctx->collection, base)
{
Object *ob = base->object;
if ((base->flag & BASE_VISIBLED) && ob != ctx->obedit && is_child(ob, parent)) {
DupliContext pctx;
- copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false);
+ copy_dupli_context(&pctx, ctx, ctx->object, NULL, collectionid, false);
/* mballs have a different dupli handling */
if (ob->type != OB_MBALL) {
@@ -255,9 +255,9 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
}
make_child_duplis_cb(&pctx, userdata, ob);
}
- groupid++;
+ collectionid++;
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
}
else {
int baseid = 0;
@@ -281,54 +281,55 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
/*---- Implementations ----*/
-/* OB_DUPLIGROUP */
-static void make_duplis_group(const DupliContext *ctx)
+/* OB_DUPLICOLLECTION */
+static void make_duplis_collection(const DupliContext *ctx)
{
Object *ob = ctx->object;
- Group *group;
+ Collection *collection;
Base *base;
- float group_mat[4][4];
+ float collection_mat[4][4];
int id;
bool animated;
if (ob->dup_group == NULL) return;
- group = ob->dup_group;
+ collection = ob->dup_group;
- /* combine group offset and obmat */
- unit_m4(group_mat);
- sub_v3_v3(group_mat[3], group->dupli_ofs);
- mul_m4_m4m4(group_mat, ob->obmat, group_mat);
+ /* combine collection offset and obmat */
+ unit_m4(collection_mat);
+ sub_v3_v3(collection_mat[3], collection->dupli_ofs);
+ mul_m4_m4m4(collection_mat, ob->obmat, collection_mat);
/* don't access 'ob->obmat' from now on. */
- /* handles animated groups */
+ /* handles animated collections */
/* we need to check update for objects that are not in scene... */
if (ctx->do_update) {
/* note: update is optional because we don't always need object
* transformations to be correct. Also fixes bug [#29616]. */
- BKE_group_handle_recalc_and_update(ctx->depsgraph, ctx->scene, ob, group);
+ BKE_collection_handle_recalc_and_update(ctx->depsgraph, ctx->scene, ob, collection);
}
- animated = BKE_group_is_animated(group, ob);
+ animated = BKE_collection_is_animated(collection, ob);
- for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) {
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(collection);
+ for (base = dup_collection_objects.first, id = 0; base; base = base->next, id++) {
if (base->object != ob && (base->flag & BASE_VISIBLED)) {
float mat[4][4];
- /* group dupli offset, should apply after everything else */
- mul_m4_m4m4(mat, group_mat, base->object->obmat);
+ /* collection dupli offset, should apply after everything else */
+ mul_m4_m4m4(mat, collection_mat, base->object->obmat);
make_dupli(ctx, base->object, mat, id, animated, false);
/* recursion */
- make_recursive_duplis(ctx, base->object, group_mat, id, animated);
+ make_recursive_duplis(ctx, base->object, collection_mat, id, animated);
}
}
}
-static const DupliGenerator gen_dupli_group = {
- OB_DUPLIGROUP, /* type */
- make_duplis_group /* make_duplis */
+static const DupliGenerator gen_dupli_collection = {
+ OB_DUPLICOLLECTION, /* type */
+ make_duplis_collection /* make_duplis */
};
/* OB_DUPLIFRAMES */
@@ -341,8 +342,8 @@ static void make_duplis_frames(const DupliContext *ctx)
int cfrao = scene->r.cfra;
int dupend = ob->dupend;
- /* dupliframes not supported inside groups */
- if (ctx->group)
+ /* dupliframes not supported inside collections */
+ if (ctx->collection)
return;
/* if we don't have any data/settings which will lead to object movement,
* don't waste time trying, as it will all look the same...
@@ -601,8 +602,8 @@ static void make_duplis_font(const DupliContext *ctx)
const wchar_t *text = NULL;
bool text_free = false;
- /* font dupliverts not supported inside groups */
- if (ctx->group)
+ /* font dupliverts not supported inside collections */
+ if (ctx->collection)
return;
copy_m4_m4(pmat, par->obmat);
@@ -851,7 +852,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
float (*obmat)[4];
int a, b, hair = 0;
- int totpart, totchild, totgroup = 0 /*, pa_num */;
+ int totpart, totchild, totcollection = 0 /*, pa_num */;
int no_draw_flag = PARS_UNEXIST;
@@ -891,10 +892,14 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
return;
}
else { /*PART_DRAW_GR */
- if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->view_layer->object_bases))
+ if (part->dup_group == NULL)
return;
- if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) {
+ const ListBase dup_collection_objects = BKE_collection_object_cache_get(part->dup_group);
+ if (BLI_listbase_is_empty(&dup_collection_objects))
+ return;
+
+ if (BLI_findptr(&dup_collection_objects, par, offsetof(Base, object))) {
return;
}
}
@@ -918,31 +923,31 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
/* gather list of objects or single object */
if (part->ren_as == PART_DRAW_GR) {
if (ctx->do_update) {
- BKE_group_handle_recalc_and_update(ctx->depsgraph, scene, par, part->dup_group);
+ BKE_collection_handle_recalc_and_update(ctx->depsgraph, scene, par, part->dup_group);
}
if (part->draw & PART_DRAW_COUNT_GR) {
for (dw = part->dupliweights.first; dw; dw = dw->next)
- totgroup += dw->count;
+ totcollection += dw->count;
}
else {
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
(void) object;
- totgroup++;
+ totcollection++;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* we also copy the actual objects to restore afterwards, since
* BKE_object_where_is_calc_time will change the object which breaks transform */
- oblist = MEM_callocN((size_t)totgroup * sizeof(Object *), "dupgroup object list");
- obcopylist = MEM_callocN((size_t)totgroup * sizeof(Object), "dupgroup copy list");
+ oblist = MEM_callocN((size_t)totcollection * sizeof(Object *), "dupcollection object list");
+ obcopylist = MEM_callocN((size_t)totcollection * sizeof(Object), "dupcollection copy list");
- if (part->draw & PART_DRAW_COUNT_GR && totgroup) {
+ if (part->draw & PART_DRAW_COUNT_GR && totcollection) {
dw = part->dupliweights.first;
- for (a = 0; a < totgroup; dw = dw->next) {
+ for (a = 0; a < totcollection; dw = dw->next) {
for (b = 0; b < dw->count; b++, a++) {
oblist[a] = dw->ob;
obcopylist[a] = *dw->ob;
@@ -951,17 +956,17 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
else {
a = 0;
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
oblist[a] = object;
obcopylist[a] = *object;
a++;
- if (a >= totgroup) {
+ if (a >= totcollection) {
continue;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
else {
@@ -1003,14 +1008,14 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->ren_as == PART_DRAW_GR) {
/* prevent divide by zero below [#28336] */
- if (totgroup == 0)
+ if (totcollection == 0)
continue;
- /* for groups, pick the object based on settings */
+ /* for collections, pick the object based on settings */
if (part->draw & PART_DRAW_RAND_GR)
- b = BLI_rand() % totgroup;
+ b = BLI_rand() % totcollection;
else
- b = a % totgroup;
+ b = a % totcollection;
ob = oblist[b];
obmat = oblist[b]->obmat;
@@ -1051,7 +1056,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
b = 0;
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
copy_m4_m4(tmat, oblist[b]->obmat);
@@ -1059,7 +1064,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
mul_mat3_m4_fl(tmat, size * scale);
mul_v3_fl(tmat[3], size * scale);
- /* group dupli offset, should apply after everything else */
+ /* collection dupli offset, should apply after everything else */
if (!is_zero_v3(part->dup_group->dupli_ofs)) {
sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
}
@@ -1076,7 +1081,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
b++;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
else {
/* to give ipos in object correct offset */
@@ -1130,7 +1135,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
/* restore objects since they were changed in BKE_object_where_is_calc_time */
if (part->ren_as == PART_DRAW_GR) {
- for (a = 0; a < totgroup; a++)
+ for (a = 0; a < totcollection; a++)
*(oblist[a]) = obcopylist[a];
}
else
@@ -1201,8 +1206,8 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
else if (transflag & OB_DUPLIFRAMES) {
return &gen_dupli_frames;
}
- else if (transflag & OB_DUPLIGROUP) {
- return &gen_dupli_group;
+ else if (transflag & OB_DUPLICOLLECTION) {
+ return &gen_dupli_collection;
}
return NULL;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index dacd826084f..26c822f5fef 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -65,10 +65,10 @@
#include "BKE_boids.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_colortools.h"
#include "BKE_effect.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_main.h"
#include "BKE_lattice.h"
@@ -372,13 +372,19 @@ void psys_check_group_weights(ParticleSettings *part)
ParticleDupliWeight *dw, *tdw;
int current = 0;
- if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->view_layer->object_bases.first) {
+ if (part->ren_as != PART_DRAW_GR || !part->dup_group) {
+ BLI_freelistN(&part->dupliweights);
+ return;
+ }
+
+ const ListBase dup_group_objects = BKE_collection_object_cache_get(part->dup_group);
+ if (dup_group_objects.first) {
/* First try to find NULL objects from their index,
* and remove all weights that don't have an object in the group. */
dw = part->dupliweights.first;
while (dw) {
- if (dw->ob == NULL || !BKE_group_object_exists(part->dup_group, dw->ob)) {
- Base *base = BLI_findlink(&part->dup_group->view_layer->object_bases, dw->index);
+ if (dw->ob == NULL || !BKE_collection_has_object_recursive(part->dup_group, dw->ob)) {
+ Base *base = BLI_findlink(&dup_group_objects, dw->index);
if (base != NULL) {
dw->ob = base->object;
}
@@ -394,7 +400,7 @@ void psys_check_group_weights(ParticleSettings *part)
}
/* then add objects in the group to new list */
- FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object)
{
dw = part->dupliweights.first;
while (dw && dw->ob != object) {
@@ -408,7 +414,7 @@ void psys_check_group_weights(ParticleSettings *part)
BLI_addtail(&part->dupliweights, dw);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
dw = part->dupliweights.first;
for (; dw; dw = dw->next) {
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 12b197070a2..7fd7b791a3f 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -59,6 +59,7 @@
#include "BKE_appdir.h"
#include "BKE_anim.h"
#include "BKE_cloth.h"
+#include "BKE_collection.h"
#include "BKE_dynamicpaint.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -1741,8 +1742,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
* for baking with linking dupligroups. Once we have better overrides
* this can be revisited so users select the local objects directly. */
if (scene && (duplis-- > 0) && (ob->dup_group)) {
- Group *group = ob->dup_group;
- Base *base = group->view_layer->object_bases.first;
+ Collection *collection = ob->dup_group;
+ Base *base = BKE_collection_object_cache_get(collection).first;
for (; base; base = base->next) {
if (base->object != ob) {
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 1c16d57ab12..5a9b5585efd 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -55,9 +55,9 @@
#include "DNA_scene_types.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_collection.h"
#include "BKE_effect.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_mesh.h"
@@ -94,7 +94,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (rbw->physics_world) {
/* free physics references, we assume that all physics objects in will have been added to the world */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
{
if (object->rigidbody_constraint) {
RigidBodyCon *rbc = object->rigidbody_constraint;
@@ -103,11 +103,11 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
if (rbw->group) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
{
if (object->rigidbody_object) {
RigidBodyOb *rbo = object->rigidbody_object;
@@ -116,7 +116,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
@@ -1156,7 +1156,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object from rigid body constraints */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, obt)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, obt)
{
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
@@ -1165,7 +1165,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
}
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
}
@@ -1199,9 +1199,10 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
/* Update object array and rigid body count so they're in sync with the rigid body group */
static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
{
+ const ListBase objects = BKE_collection_object_cache_get(rbw->group);
int i, n;
- n = BLI_listbase_count(&rbw->group->view_layer->object_bases);
+ n = BLI_listbase_count(&objects);
if (rbw->numbodies != n) {
rbw->numbodies = n;
@@ -1209,12 +1210,12 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
}
i = 0;
- FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
{
rbw->objects[i] = object;
i++;
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
@@ -1340,7 +1341,7 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
* Memory management needs redesign here, this is just a dirty workaround.
*/
if (rebuild && rbw->constraints) {
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, ob)
{
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc && rbc->physics_constraint) {
@@ -1349,11 +1350,11 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
rbc->physics_constraint = NULL;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* update objects */
- FOREACH_GROUP_OBJECT_BEGIN(rbw->group, ob)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, ob)
{
if (ob->type == OB_MESH) {
/* validate that we've got valid object set up here... */
@@ -1396,13 +1397,13 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
rigidbody_update_sim_ob(depsgraph, scene, rbw, ob, rbo);
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
/* update constraints */
if (rbw->constraints == NULL) /* no constraints, move on */
return;
- FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, ob)
{
/* validate that we've got valid object set up here... */
RigidBodyCon *rbc = ob->rigidbody_constraint;
@@ -1430,12 +1431,12 @@ static void rigidbody_update_simulation(struct Depsgraph *depsgraph, Scene *scen
rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
}
}
- FOREACH_GROUP_OBJECT_END;
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
{
- FOREACH_GROUP_BASE_BEGIN(rbw->group, base)
+ FOREACH_COLLECTION_BASE_RECURSIVE_BEGIN(rbw->group, base)
{
Object *ob = base->object;
RigidBodyOb *rbo = ob->rigidbody_object;
@@ -1448,7 +1449,7 @@ static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
RB_body_deactivate(rbo->physics_object);
}
}
- FOREACH_GROUP_BASE_END
+ FOREACH_COLLECTION_BASE_RECURSIVE_END
}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
@@ -1575,7 +1576,8 @@ void BKE_rigidbody_rebuild_world(struct Depsgraph *depsgraph, Scene *scene, floa
cache = rbw->pointcache;
/* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
- if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->view_layer->object_bases)) {
+ const ListBase objects = BKE_collection_object_cache_get(rbw->group);
+ if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&objects)) {
cache->flag |= PTCACHE_OUTDATED;
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 950db7d7453..ea0498930ff 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -75,7 +75,6 @@
#include "BKE_freestyle.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
-#include "BKE_group.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
@@ -244,20 +243,18 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->depsgraph_hash = NULL;
sce_dst->fps_info = NULL;
- /* layers and collections */
- sce_dst->collection = MEM_dupallocN(sce_src->collection);
- SceneCollection *mc_src = BKE_collection_master(&sce_src->id);
- SceneCollection *mc_dst = BKE_collection_master(&sce_dst->id);
-
- /* Recursively creates a new SceneCollection tree. */
- BKE_collection_copy_data(mc_dst, mc_src, flag_subdata);
+ /* Master Collection */
+ if (sce_src->master_collection) {
+ sce_dst->master_collection = BKE_collection_copy_master(bmain, sce_src->master_collection, flag);
+ }
+ /* View Layers */
BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers);
for (ViewLayer *view_layer_src = sce_src->view_layers.first, *view_layer_dst = sce_dst->view_layers.first;
view_layer_src;
view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next)
{
- BKE_view_layer_copy_data(view_layer_dst, view_layer_src, mc_dst, mc_src, flag_subdata);
+ BKE_view_layer_copy_data(sce_dst, sce_src, view_layer_dst, view_layer_src, flag_subdata);
}
BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers));
@@ -407,6 +404,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_id_copy_ex(bmain, (ID *)sce_copy->world, (ID **)&sce_copy->world, LIB_ID_COPY_ACTIONS, false);
}
+ /* Collections */
+ BKE_collection_copy_full(bmain, sce_copy->master_collection);
+
/* Full copy of GreasePencil. */
/* XXX Not copying anim/actions here? */
if (sce_copy->gpd) {
@@ -506,9 +506,15 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
}
/* Master Collection */
- BKE_collection_master_free(&sce->id, do_id_user);
- MEM_freeN(sce->collection);
- sce->collection = NULL;
+ // TODO: what to do with do_id_user? it's also true when just
+ // closing the file which seems wrong? should decrement users
+ // for objects directly in the master collection? then other
+ // collections in the scene need to do it too?
+ if (sce->master_collection) {
+ BKE_collection_free(sce->master_collection);
+ MEM_freeN(sce->master_collection);
+ sce->master_collection = NULL;
+ }
/* These are freed on doversion. */
BLI_assert(sce->layer_properties == NULL);
@@ -789,8 +795,7 @@ void BKE_scene_init(Scene *sce)
sce->orientation_index_custom = -1;
/* Master Collection */
- sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
- BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+ sce->master_collection = BKE_collection_master_add();
BKE_view_layer_add(sce, "View Layer");
@@ -910,29 +915,19 @@ Object *BKE_scene_object_find_by_name(Scene *scene, const char *name)
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
Object *ob;
- Group *group;
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
/* deselect objects (for dataselect) */
for (ob = bmain->object.first; ob; ob = ob->id.next)
- ob->flag &= ~(SELECT | OB_FROMGROUP);
-
- /* group flags again */
- for (group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT_BEGIN(group, object)
- {
- object->flag |= OB_FROMGROUP;
- }
- FOREACH_GROUP_OBJECT_END;
- }
+ ob->flag &= ~SELECT;
/* copy layers and flags from bases to objects */
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
ob = base->object;
- /* group patch... */
+ /* collection patch... */
BKE_scene_object_base_flag_sync_from_base(base);
}
}
@@ -1025,9 +1020,9 @@ int BKE_scene_base_iter_next(
else {
if (iter->phase != F_DUPLI) {
if (depsgraph && (*base)->object->transflag & OB_DUPLI) {
- /* groups cannot be duplicated for mballs yet,
+ /* collections cannot be duplicated for mballs yet,
* this enters eternal loop because of
- * makeDispListMBall getting called inside of group_duplilist */
+ * makeDispListMBall getting called inside of collection_duplilist */
if ((*base)->object->dup_group == NULL) {
iter->duplilist = object_duplilist_ex(depsgraph, (*scene), (*base)->object, false);
@@ -1087,11 +1082,11 @@ int BKE_scene_base_iter_next(
return iter->phase;
}
-Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection)
+Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection)
{
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
for (ViewLayer *layer = scene->view_layers.first; layer; layer = layer->next) {
- if (BKE_view_layer_has_collection(layer, scene_collection)) {
+ if (BKE_view_layer_has_collection(layer, collection)) {
return scene;
}
}
@@ -1555,11 +1550,7 @@ void BKE_scene_object_base_flag_sync_from_base(Base *base)
{
Object *ob = base->object;
- /* keep the object only flags untouched */
- int flag = ob->flag & OB_FROMGROUP;
-
ob->flag = base->flag;
- ob->flag |= flag;
if ((base->flag & BASE_SELECTED) != 0) {
ob->flag |= SELECT;
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 0af400796a4..9aa6c172a90 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -71,10 +71,10 @@ variables on the UI for now
#include "BLI_ghash.h"
#include "BLI_threads.h"
+#include "BKE_collection.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_global.h"
-#include "BKE_group.h"
#include "BKE_modifier.h"
#include "BKE_softbody.h"
#include "BKE_pointcache.h"
@@ -514,20 +514,18 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
}
/**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
*/
-static void ccd_build_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash(ViewLayer *view_layer, Collection *collection, Object *vertexowner, GHash *hash)
{
Object *ob;
if (!hash) return;
- /* Explicit collision group. */
- if (group) {
- view_layer = group->view_layer;
- }
+ /* Explicit collision collection. */
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection);
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (; base; base = base->next) {
/* Only proceed for mesh object in same layer. */
if (base->object->type == OB_MESH) {
ob = base->object;
@@ -551,20 +549,18 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
}
/**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
*/
-static void ccd_update_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_update_deflector_hash(ViewLayer *view_layer, Collection *collection, Object *vertexowner, GHash *hash)
{
Object *ob;
if ((!hash) || (!vertexowner)) return;
- /* Explicit collision group. */
- if (group) {
- view_layer = group->view_layer;
- }
+ /* Explicit collision collection. */
+ Base *base = BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection);
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (; base; base = base->next) {
/* Only proceed for mesh object in same layer. */
if (base->object->type == OB_MESH) {
ob = base->object;
@@ -964,11 +960,11 @@ static void free_softbody_intern(SoftBody *sb)
/* +++ dependency information functions*/
/**
- * \note group overrides scene when not NULL.
+ * \note collection overrides scene when not NULL.
*/
-static bool are_there_deflectors(ViewLayer *view_layer)
+static bool are_there_deflectors(Base *first_base)
{
- for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ for (Base *base = first_base; base; base = base->next) {
if (base->object->pd) {
if (base->object->pd->deflect)
return 1;
@@ -978,9 +974,9 @@ static bool are_there_deflectors(ViewLayer *view_layer)
return 0;
}
-static int query_external_colliders(ViewLayer *view_layer, Group *group)
+static int query_external_colliders(ViewLayer *view_layer, Collection *collection)
{
- return(are_there_deflectors(group != NULL ? group->view_layer : view_layer));
+ return(are_there_deflectors(BKE_collection_or_layer_objects(NULL, NULL, view_layer, collection)));
}
/* --- dependency information functions*/