void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local) { bool is_local = false, is_lib = false; /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ if (!ID_IS_LINKED_DATABLOCK(brush)) { return; } if (brush->clone.image) { /* Special case: ima always local immediately. Clone image should only have one user anyway. */ id_make_local(bmain, &brush->clone.image->id, false, false); } BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib); if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &brush->id); BKE_id_expand_local(&brush->id); /* enable fake user by default */ id_fake_user_set(&brush->id); } else { Brush *brush_new = BKE_brush_copy(bmain, brush); /* Ensures FAKE_USER is set */ brush_new->id.us = 0; /* setting newid is mandatory for complex make_lib_local logic... */ ID_NEW_SET(brush, brush_new); if (!lib_local) { BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE); } } } }
static Collection *collection_duplicate_recursive(Main *bmain, Collection *parent, Collection *collection_old, const bool do_hierarchy, const bool do_objects, const bool do_obdata) { Collection *collection_new; bool do_full_process = false; const int object_dupflag = (do_obdata) ? U.dupflag : 0; if (!do_hierarchy || collection_old->id.newid == NULL) { BKE_id_copy(bmain, &collection_old->id, (ID **)&collection_new); id_us_min( &collection_new->id); /* Copying add one user by default, need to get rid of that one. */ if (do_hierarchy) { ID_NEW_SET(collection_old, collection_new); } do_full_process = true; } else { collection_new = (Collection *)collection_old->id.newid; } /* Optionally add to parent (we always want to do that, * even if collection_old had already been duplicated). */ if (parent != NULL) { if (collection_child_add(parent, collection_new, 0, true)) { /* Put collection right after existing one. */ CollectionChild *child = collection_find_child(parent, collection_old); 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); } } } /* If we are not doing any kind of deep-copy, we can return immediately. * False do_full_process means collection_old had already been duplicated, * no need to redo some deep-copy on it. */ if (!do_hierarchy || !do_full_process) { return collection_new; } if (do_objects) { /* We can loop on collection_old's objects, that list is currently identical the collection_new * objects, and won't be changed here. */ for (CollectionObject *cob = collection_old->gobject.first; cob; cob = cob->next) { Object *ob_old = cob->ob; Object *ob_new = (Object *)ob_old->id.newid; if (ob_new == NULL) { ob_new = BKE_object_duplicate(bmain, ob_old, object_dupflag); ID_NEW_SET(ob_old, ob_new); } collection_object_add(bmain, collection_new, ob_new, 0, true); collection_object_remove(bmain, collection_new, ob_old, false); } } /* We can loop on collection_old's children, * that list is currently identical the collection_new' children, and won't be changed here. */ for (CollectionChild *child = collection_old->children.first; child; child = child->next) { Collection *child_collection_old = child->collection; collection_duplicate_recursive( bmain, collection_new, child_collection_old, do_hierarchy, do_objects, do_obdata); collection_child_remove(collection_new, child_collection_old); } return collection_new; }