Core: Add proper support to add or copy IDs into libraries. #108328

Merged
Bastien Montagne merged 2 commits from mont29/blender:F-idcopy-linkeddata into main 2024-03-06 17:05:21 +01:00
39 changed files with 456 additions and 100 deletions

View File

@ -8,6 +8,8 @@
* \ingroup bke
*/
#include <optional>
#include "BLI_sys_types.h" /* for bool */
struct AnimData;
@ -15,6 +17,7 @@ struct BlendDataReader;
struct BlendLibReader;
struct BlendWriter;
struct ID;
struct Library;
struct LibraryForeachIDData;
struct Main;
struct ReportList;
@ -84,12 +87,29 @@ void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data);
/**
* Make a copy of the given AnimData - to be used when copying data-blocks.
* \param flag: Control ID pointers management,
* see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_lib_id.hh
*
* \note: Regarding handling of IDs managed by the #AnimData struct, this function follows the
* behaviors of the generic #BKE_id_copy_ex, please see its documetation for more details.
*
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in
* #BKE_lib_id.hh
*
* \return The copied animdata.
*/
AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, int flag);
/**
* Same as #BKE_animdata_copy, but allows to duplicate Action IDs into a library.
*
* \param owner_library the Library to 'assign' the newly created ID to. Use `nullptr` to make ID
* not use any library (i.e. become a local ID). Use `std::nullopt` for default behavior (i.e.
* behavior of the #BKE_animdata_copy function).
*/
AnimData *BKE_animdata_copy_in_lib(Main *bmain,
std::optional<Library *> owner_library,
AnimData *adt,
int flag);
/**
* \param flag: Control ID pointers management,
* see LIB_ID_CREATE_.../LIB_ID_COPY_... flags in BKE_lib_id.hh

View File

@ -10,6 +10,8 @@
* ID type structure, helping to factorize common operations and data for all data-block types.
*/
#include <optional>
#include "BLI_sys_types.h"
struct AssetTypeInfo;
@ -18,6 +20,7 @@ struct BlendDataReader;
struct BlendLibReader;
struct BlendWriter;
struct ID;
struct Library;
struct LibraryForeachIDData;
struct Main;
@ -63,7 +66,8 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v);
using IDTypeInitDataFunction = void (*)(ID *id);
/** \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more). */
using IDTypeCopyDataFunction = void (*)(Main *bmain, ID *id_dst, const ID *id_src, int flag);
using IDTypeCopyDataFunction = void (*)(
Main *bmain, std::optional<Library *> owner_library, ID *id_dst, const ID *id_src, int flag);
using IDTypeFreeDataFunction = void (*)(ID *id);

View File

@ -30,6 +30,8 @@
* specific cases requiring advanced (and potentially dangerous) handling.
*/
#include <optional>
#include "BLI_compiler_attrs.h"
#include "BLI_set.hh"
#include "BLI_utildefines.h"
@ -57,13 +59,29 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name);
*/
void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT;
/**
* Allocates and returns a block of the specified type, with the specified name
* Allocates and returns an ID block of the specified type, with the specified name
* (adjusted as necessary to ensure uniqueness), and appended to the specified list.
* The user count is set to 1, all other content (apart from name and links) being
* initialized to zero.
*
* \note: By default, IDs allocated in a Main database will get the current library of the Main,
* i.e. usually (besides in readfile case), they will have a `nullptr` `lib` pointer and be local
* data. IDs allocated outside of a Main database will always get a `nullptr` `lib` pointer.
*/
void *BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag)
ATTR_WARN_UNUSED_RESULT;
/**
* Same as for #BKE_libblock_alloc, but allows creating a data-block for a given owner library.
*
* \param owner_library the Library to 'assign' the newly created ID to. Use `nullptr` to make ID
* not use any library (i.e. become a local ID). Use `std::nullopt` for default behavior (i.e.
* behavior of the #BKE_libblock_alloc function).
*/
void *BKE_libblock_alloc_in_lib(Main *bmain,
std::optional<Library *> owner_library,
short type,
const char *name,
int flag) ATTR_WARN_UNUSED_RESULT;
/**
* Initialize an ID of given type, such that it has valid 'empty' data.
* ID is assumed to be just calloc'ed.
@ -102,9 +120,24 @@ void BKE_lib_libblock_session_uid_renew(ID *id);
/**
* Generic helper to create a new empty data-block of given type in given \a bmain database.
*
* \note: By default, IDs created in a Main database will get the current library of the Main,
* i.e. usually (besides in readfile case), they will have a `nullptr` `lib` pointer and be local
* data. IDs created outside of a Main database will always get a `nullptr` `lib` pointer.
* \param name: can be NULL, in which case we get default name for this ID type.
*/
void *BKE_id_new(Main *bmain, short type, const char *name);
/**
* Same as for #BKE_id_new, but allows creating a data-block for (whithin) a given owner library.
*
* \param owner_library the Library to 'assign' the newly created ID to. Use `nullptr` to make ID
* not use any library (i.e. become a local ID). Use `std::nullopt` for default behavior (i.e.
* behavior of the #BKE_id_new function).
*/
void *BKE_id_new_in_lib(Main *bmain,
std::optional<Library *> owner_library,
short type,
const char *name);
/**
* Generic helper to create a new temporary empty data-block of given type,
* *outside* of any Main database.
@ -163,8 +196,6 @@ enum {
/* *** Ideally we should not have those, but we need them for now... *** */
/** EXCEPTION! Deep-copy actions used by animation-data of copied ID. */
LIB_ID_COPY_ACTIONS = 1 << 24,
/** Keep the library pointer when copying data-block outside of bmain. */
LIB_ID_COPY_KEEP_LIB = 1 << 25,
/** EXCEPTION! Deep-copy shape-keys used by copied obdata ID. */
LIB_ID_COPY_SHAPEKEY = 1 << 26,
/** EXCEPTION! Specific deep-copy of node trees used e.g. for rendering purposes. */
@ -188,8 +219,28 @@ enum {
};
void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, int orig_flag);
/**
* Same as #BKE_libblock_copy_ex, but allows copying data into a library, and not as local data
* only.
*
* \param owner_library the Library to 'assign' the newly created ID to. Use `nullptr` to make ID
* not use any library (i.e. become a local ID). Use std::nullopt for default behavior (i.e.
* behavior of the #BKE_libblock_copy_ex function).
*/
void BKE_libblock_copy_in_lib(Main *bmain,
std::optional<Library *> owner_library,
const ID *id,
ID **r_newid,
int orig_flag);
/**
* Used everywhere in blenkernel.
*
* \note Typically, the newly copied ID will be a local data (its `lib` pointer will be `nullptr`).
* In practice, ID copying follows the same behavior as ID creation (see #BKE_libblock_alloc
* documentation), with one special case: when the special flag #LIB_ID_CREATE_NO_ALLOCATE is
* specified, the copied ID will have the same library as the source ID.
*
*/
void *BKE_libblock_copy(Main *bmain, const ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
@ -436,6 +487,11 @@ bool BKE_id_copy_is_allowed(const ID *id);
*
* \note User-count of new copy is always set to 1.
*
* \note Typically, the newly copied ID will be a local data (its `lib` pointer will be `nullptr`).
* In practice, ID copying follows the same behavior as ID creation (see #BKE_libblock_alloc
* documentation), with one special case: when the special flag #LIB_ID_CREATE_NO_ALLOCATE is
* specified, the copied ID will have the same library as the source ID.
*
* \param bmain: Main database, may be NULL only if LIB_ID_CREATE_NO_MAIN is specified.
* \param id: Source data-block.
* \param r_newid: Pointer to new (copied) ID pointer, may be NULL.
@ -445,6 +501,17 @@ bool BKE_id_copy_is_allowed(const ID *id);
* \return NULL when copying that ID type is not supported, the new copy otherwise.
*/
ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, int flag);
/**
* Enable coying non-local data into libraries.
*
* See #BKE_id_copy_ex for details.
*
* \param owner_library the Library to 'assign' the newly created ID to. Use `nullptr` to make ID
* not use any library (i.e. become a local ID). Use std::nullopt for default behavior (i.e.
* behavior of the #BKE_id_copy_ex function).
*/
struct ID *BKE_id_copy_in_lib(
Main *bmain, std::optional<Library *> owner_library, const ID *id, ID **r_newid, int flag);
/**
* Invoke the appropriate copy method for the block and return the new id as result.
*

View File

@ -10,6 +10,7 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -97,7 +98,11 @@ static CLG_LogRef LOG = {"bke.action"};
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void action_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void action_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
bAction *action_dst = (bAction *)id_dst;
const bAction *action_src = (const bAction *)id_src;

View File

@ -8,6 +8,7 @@
#include "MEM_guardedalloc.h"
#include <cstring>
#include <optional>
#include "BKE_action.h"
#include "BKE_anim_data.hh"
@ -303,7 +304,10 @@ void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
/* Copying -------------------------------------------- */
AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
AnimData *BKE_animdata_copy_in_lib(Main *bmain,
std::optional<Library *> owner_library,
AnimData *adt,
const int flag)
{
AnimData *dadt;
@ -333,8 +337,10 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
flag;
BLI_assert(bmain != nullptr);
BLI_assert(dadt->action == nullptr || dadt->action != dadt->tmpact);
dadt->action = (bAction *)BKE_id_copy_ex(bmain, (ID *)dadt->action, nullptr, id_copy_flag);
dadt->tmpact = (bAction *)BKE_id_copy_ex(bmain, (ID *)dadt->tmpact, nullptr, id_copy_flag);
dadt->action = reinterpret_cast<bAction *>(BKE_id_copy_in_lib(
bmain, owner_library, reinterpret_cast<ID *>(dadt->action), nullptr, id_copy_flag));
dadt->tmpact = reinterpret_cast<bAction *>(BKE_id_copy_in_lib(
bmain, owner_library, reinterpret_cast<ID *>(dadt->tmpact), nullptr, id_copy_flag));
}
else if (do_id_user) {
id_us_plus((ID *)dadt->action);
@ -355,6 +361,11 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
return dadt;
}
AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const int flag)
{
return BKE_animdata_copy_in_lib(bmain, std::nullopt, adt, flag);
}
bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag)
{
AnimData *adt;

View File

@ -13,6 +13,7 @@
#include <cstdlib>
#include <cstring>
#include <limits>
#include <optional>
#include "MEM_guardedalloc.h"
@ -130,7 +131,11 @@ static void copy_bone_collection(bArmature *armature_dst,
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void armature_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void armature_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
bArmature *armature_dst = (bArmature *)id_dst;
const bArmature *armature_src = (const bArmature *)id_src;

View File

@ -5,6 +5,7 @@
/** \file
* \ingroup bke
*/
#include <optional>
#include "MEM_guardedalloc.h"
@ -55,7 +56,11 @@ static void brush_init_data(ID *id)
BKE_brush_curve_preset(brush, CURVE_PRESET_SMOOTH);
}
static void brush_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void brush_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
Brush *brush_dst = (Brush *)id_dst;
const Brush *brush_src = (const Brush *)id_src;

View File

@ -7,6 +7,7 @@
*/
#include <cstring>
#include <optional>
#include "DNA_cachefile_types.h"
#include "DNA_object_types.h"
@ -59,6 +60,7 @@ static void cache_file_init_data(ID *id)
}
static void cache_file_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)

View File

@ -8,6 +8,7 @@
#include <cstddef>
#include <cstdlib>
#include <optional>
/* Allow using deprecated functionality for .blend file I/O. */
#define DNA_DEPRECATED_ALLOW
@ -68,7 +69,11 @@ static void camera_init_data(ID *id)
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void camera_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void camera_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
Camera *cam_dst = (Camera *)id_dst;
const Camera *cam_src = (const Camera *)id_src;

View File

@ -12,6 +12,7 @@
#include "CLG_log.h"
#include <cstring>
#include <optional>
#include "BLI_blenlib.h"
#include "BLI_iterator.h"
@ -132,7 +133,11 @@ static void collection_init_data(ID *id)
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void collection_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void collection_copy_data(Main *bmain,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
Collection *collection_dst = (Collection *)id_dst;
const Collection *collection_src = (const Collection *)id_src;
@ -929,13 +934,15 @@ Collection *BKE_collection_master_add(Scene *scene)
BLI_assert(scene != nullptr && scene->master_collection == nullptr);
/* Not an actual datablock, but owned by scene. */
Collection *master_collection = static_cast<Collection *>(
BKE_libblock_alloc(nullptr, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN));
Collection *master_collection = static_cast<Collection *>(BKE_libblock_alloc_in_lib(
nullptr, scene->id.lib, ID_GR, BKE_SCENE_COLLECTION_NAME, LIB_ID_CREATE_NO_MAIN));
master_collection->id.flag |= LIB_EMBEDDED_DATA;
master_collection->owner_id = &scene->id;
master_collection->flag |= COLLECTION_IS_MASTER;
master_collection->color_tag = COLLECTION_COLOR_NONE;
BLI_assert(scene->id.lib == master_collection->id.lib);
return master_collection;
}

View File

@ -9,6 +9,7 @@
#include <cmath> /* floor */
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -79,7 +80,11 @@ static void curve_init_data(ID *id)
MEMCPY_STRUCT_AFTER(curve, DNA_struct_default_get(Curve), id);
}
static void curve_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void curve_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Curve *curve_dst = (Curve *)id_dst;
const Curve *curve_src = (const Curve *)id_src;
@ -97,7 +102,7 @@ static void curve_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
curve_dst->bevel_profile = BKE_curveprofile_copy(curve_src->bevel_profile);
if (curve_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &curve_src->key->id, (ID **)&curve_dst->key, flag);
BKE_id_copy_in_lib(bmain, owner_library, &curve_src->key->id, (ID **)&curve_dst->key, flag);
/* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */
curve_dst->key->from = &curve_dst->id;
}

View File

@ -8,6 +8,7 @@
#include <cmath>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -61,7 +62,11 @@ static void curves_init_data(ID *id)
new (&curves->geometry) blender::bke::CurvesGeometry();
}
static void curves_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void curves_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
Curves *curves_dst = (Curves *)id_dst;
const Curves *curves_src = (const Curves *)id_src;

View File

@ -11,6 +11,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "CLG_log.h"
@ -59,6 +60,7 @@
static CLG_LogRef LOG = {"bke.gpencil"};
static void greasepencil_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
@ -1059,7 +1061,7 @@ bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool in
}
/* Copy internal data (layers, etc.) */
greasepencil_copy_data(bmain, &gpd_dst->id, &gpd_src->id, 0);
greasepencil_copy_data(bmain, std::nullopt, &gpd_dst->id, &gpd_src->id, 0);
/* return new */
return gpd_dst;

View File

@ -7,6 +7,7 @@
*/
#include <iostream>
#include <optional>
#include "BKE_action.h"
#include "BKE_anim_data.hh"
@ -88,6 +89,7 @@ static void grease_pencil_init_data(ID *id)
}
static void grease_pencil_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)

View File

@ -12,6 +12,7 @@
#include <cstring>
#include <ctime>
#include <fcntl.h>
#include <optional>
#ifndef WIN32
# include <unistd.h>
#else
@ -156,7 +157,11 @@ static void image_init_data(ID *id)
}
}
static void image_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void image_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
Image *image_dst = (Image *)id_dst;
const Image *image_src = (const Image *)id_src;

View File

@ -9,6 +9,7 @@
#include <cmath>
#include <cstddef>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -54,7 +55,11 @@
#include "BLO_read_write.hh"
static void shapekey_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void shapekey_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
Key *key_dst = (Key *)id_dst;
const Key *key_src = (const Key *)id_src;

View File

@ -56,7 +56,11 @@ static void lattice_init_data(ID *id)
BKE_lattice_resize(lattice, 2, 2, 2, nullptr); /* creates a uniform lattice */
}
static void lattice_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void lattice_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Lattice *lattice_dst = (Lattice *)id_dst;
const Lattice *lattice_src = (const Lattice *)id_src;
@ -64,7 +68,8 @@ static void lattice_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i
lattice_dst->def = static_cast<BPoint *>(MEM_dupallocN(lattice_src->def));
if (lattice_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &lattice_src->key->id, (ID **)&lattice_dst->key, flag);
BKE_id_copy_in_lib(
bmain, owner_library, &lattice_src->key->id, (ID **)&lattice_dst->key, flag);
/* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */
lattice_dst->key->from = &lattice_dst->id;
}

View File

@ -626,19 +626,28 @@ bool BKE_id_copy_is_allowed(const ID *id)
#undef LIB_ID_TYPES_NOCOPY
}
ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
ID *BKE_id_copy_in_lib(Main *bmain,
std::optional<Library *> owner_library,
const ID *id,
ID **r_newid,
const int flag)
{
ID *newid = (r_newid != nullptr) ? *r_newid : nullptr;
BLI_assert_msg(newid || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0,
"Copying with 'no allocate' behavior should always get a non-null new ID buffer");
/* Make sure destination pointer is all good. */
if ((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0) {
newid = nullptr;
}
else {
if (newid != nullptr) {
/* Allow some garbage non-initialized memory to go in, and clean it up here. */
const size_t size = BKE_libblock_get_alloc_info(GS(id->name), nullptr);
memset(newid, 0, size);
if (!newid) {
/* Invalid case, already caught by the assert above. */
return nullptr;
}
/* Allow some garbage non-initialized memory to go in, and clean it up here. */
const size_t size = BKE_libblock_get_alloc_info(GS(id->name), nullptr);
memset(newid, 0, size);
}
/* Early output if source is nullptr. */
@ -653,16 +662,21 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
return nullptr;
}
BKE_libblock_copy_ex(bmain, id, &newid, flag);
BKE_libblock_copy_in_lib(bmain, owner_library, id, &newid, flag);
if (idtype_info->copy_data != nullptr) {
idtype_info->copy_data(bmain, newid, id, flag);
idtype_info->copy_data(bmain, owner_library, newid, id, flag);
}
}
else {
BLI_assert_msg(0, "IDType Missing IDTypeInfo");
}
BLI_assert_msg(newid, "Could not get an allocated new ID to copy into");
if (!newid) {
return nullptr;
}
/* Update ID refcount, remap pointers to self in new ID. */
IDCopyLibManagementData data{};
data.id_src = id;
@ -673,11 +687,20 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
/* Do not make new copy local in case we are copying outside of main...
* XXX TODO: is this behavior OK, or should we need own flag to control that? */
if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
BLI_assert((flag & LIB_ID_COPY_KEEP_LIB) == 0);
lib_id_copy_ensure_local(bmain, id, newid, 0);
BLI_assert(!owner_library || newid->lib == *owner_library);
if (!ID_IS_LINKED(newid)) {
lib_id_copy_ensure_local(bmain, id, newid, 0);
}
}
else {
newid->lib = id->lib;
/* NOTE: Do not call `ensure_local` for IDs copied outside of Main, even if they do become
* local.
*
* Most of the time, this would not be the desired behavior currently.
*
* In the few cases where this is actually needed (e.g. from liboverride resync code, see
* #lib_override_library_create_from), calling code is responsible for this. */
newid->lib = owner_library ? *owner_library : id->lib;
}
if (r_newid != nullptr) {
@ -687,9 +710,14 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
return newid;
}
ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
{
return BKE_id_copy_in_lib(bmain, std::nullopt, id, r_newid, flag);
}
ID *BKE_id_copy(Main *bmain, const ID *id)
{
return BKE_id_copy_ex(bmain, id, nullptr, LIB_ID_COPY_DEFAULT);
return BKE_id_copy_in_lib(bmain, std::nullopt, id, nullptr, LIB_ID_COPY_DEFAULT);
}
ID *BKE_id_copy_for_duplicate(Main *bmain,
@ -1220,7 +1248,11 @@ void *BKE_libblock_alloc_notest(short type)
return nullptr;
}
void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
void *BKE_libblock_alloc_in_lib(Main *bmain,
std::optional<Library *> owner_library,
short type,
const char *name,
const int flag)
{
BLI_assert((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != nullptr);
@ -1250,20 +1282,44 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
BLI_assert(bmain->is_locked_for_linking == false || ELEM(type, ID_WS, ID_GR, ID_NT));
ListBase *lb = which_libbase(bmain, type);
/* This is important in 'readfile doversion after liblink' context mainly, but is a good
* behavior for consistency in general: ID created for a Main should get that main's current
* library pointer.
*
* NOTE: A bit convoluted.
* - When Main has a defined `curlib`, it is assumed to be a split main containing only IDs
* from that library. In that case, the library can be set later, and it avoids
* synchronization issues in the namemap between the one of that temp 'library' Main and
* the library ID runtime namemap itself. In a way, the ID can be assumed local to the
* current Main, for its assignment to this Main.
* - In all other cases, the Main is assumed 'complete', i.e. containing all local and
* linked IDs, In that case, it is critical that the ID gets the correct library assigned
* now, to ensure that the call to #BKE_id_new_name_validate gives a fully valid result
* once it has been assigned to the current Main.
*/
if (bmain->curlib) {
id->lib = nullptr;
}
else {
id->lib = owner_library ? *owner_library : nullptr;
}
BKE_main_lock(bmain);
BLI_addtail(lb, id);
BKE_id_new_name_validate(bmain, lb, id, name, false);
BKE_id_new_name_validate(bmain, lb, id, name, true);
bmain->is_memfile_undo_written = false;
/* alphabetic insertion: is in new_id */
BKE_main_unlock(bmain);
/* Split Main case, now the ID should get the Main's #curlib. */
if (bmain->curlib) {
BLI_assert(!owner_library || *owner_library == bmain->curlib);
id->lib = bmain->curlib;
}
/* This assert avoids having to keep name_map consistency when changing the library of an ID,
* if this check is not true anymore it will have to be done here too. */
BLI_assert(bmain->curlib == nullptr || bmain->curlib->runtime.name_map == nullptr);
/* This is important in 'readfile doversion after liblink' context mainly, but is a good
* consistency change in general: ID created for a Main should get that main's current
* library pointer. */
id->lib = bmain->curlib;
/* TODO: to be removed from here! */
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
@ -1272,6 +1328,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
}
else {
BLI_strncpy(id->name + 2, name, sizeof(id->name) - 2);
id->lib = owner_library ? *owner_library : nullptr;
}
/* We also need to ensure a valid `session_uid` for some non-main data (like embedded IDs).
@ -1285,6 +1342,11 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
return id;
}
void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
{
return BKE_libblock_alloc_in_lib(bmain, std::nullopt, type, name, flag);
}
void BKE_libblock_init_empty(ID *id)
{
const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id);
@ -1329,7 +1391,11 @@ void BKE_lib_libblock_session_uid_renew(ID *id)
BKE_lib_libblock_session_uid_ensure(id);
}
void *BKE_id_new(Main *bmain, const short type, const char *name)
void *BKE_id_new_in_lib(Main *bmain,
std::optional<Library *> owner_library,
const short type,
const char *name)
{
BLI_assert(bmain != nullptr);
@ -1337,12 +1403,17 @@ void *BKE_id_new(Main *bmain, const short type, const char *name)
name = DATA_(BKE_idtype_idcode_to_name(type));
}
ID *id = static_cast<ID *>(BKE_libblock_alloc(bmain, type, name, 0));
ID *id = static_cast<ID *>(BKE_libblock_alloc_in_lib(bmain, owner_library, type, name, 0));
BKE_libblock_init_empty(id);
return id;
}
void *BKE_id_new(Main *bmain, const short type, const char *name)
{
return BKE_id_new_in_lib(bmain, std::nullopt, type, name);
}
void *BKE_id_new_nomain(const short type, const char *name)
{
if (name == nullptr) {
@ -1359,7 +1430,11 @@ void *BKE_id_new_nomain(const short type, const char *name)
return id;
}
void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int orig_flag)
void BKE_libblock_copy_in_lib(Main *bmain,
std::optional<Library *> owner_library,
const ID *id,
ID **r_newid,
const int orig_flag)
{
ID *new_id = *r_newid;
int flag = orig_flag;
@ -1388,10 +1463,12 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
STRNCPY(new_id->name, id->name);
new_id->us = 0;
new_id->tag |= LIB_TAG_NOT_ALLOCATED | LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT;
new_id->lib = owner_library ? *owner_library : id->lib;
/* TODO: Do we want/need to copy more from ID struct itself? */
}
else {
new_id = static_cast<ID *>(BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag));
new_id = static_cast<ID *>(
BKE_libblock_alloc_in_lib(bmain, owner_library, GS(id->name), id->name + 2, flag));
}
BLI_assert(new_id != nullptr);
@ -1451,7 +1528,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
* in their anim data *are* in bmain... super-mega-hooray. */
BLI_assert((copy_data_flag & LIB_ID_COPY_ACTIONS) == 0 ||
(copy_data_flag & LIB_ID_CREATE_NO_MAIN) == 0);
iat->adt = BKE_animdata_copy(bmain, iat->adt, copy_data_flag);
iat->adt = BKE_animdata_copy_in_lib(bmain, owner_library, iat->adt, copy_data_flag);
}
else {
iat->adt = nullptr;
@ -1465,11 +1542,16 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
*r_newid = new_id;
}
void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int orig_flag)
{
BKE_libblock_copy_in_lib(bmain, std::nullopt, id, r_newid, orig_flag);
}
void *BKE_libblock_copy(Main *bmain, const ID *id)
{
ID *idn;
BKE_libblock_copy_ex(bmain, id, &idn, 0);
BKE_libblock_copy_in_lib(bmain, std::nullopt, id, &idn, 0);
return idn;
}

View File

@ -253,11 +253,17 @@ static ID *lib_override_library_create_from(Main *bmain,
const int lib_id_copy_flags)
{
/* NOTE: do not copy possible override data from the reference here. */
ID *local_id = BKE_id_copy_ex(bmain,
reference_id,
nullptr,
LIB_ID_COPY_DEFAULT | LIB_ID_COPY_NO_LIB_OVERRIDE |
lib_id_copy_flags);
ID *local_id = BKE_id_copy_in_lib(
bmain,
owner_library,
reference_id,
nullptr,
(LIB_ID_COPY_DEFAULT | LIB_ID_COPY_NO_LIB_OVERRIDE | lib_id_copy_flags));
if (local_id == nullptr) {
return nullptr;
}
BLI_assert(local_id->lib == owner_library);
id_us_min(local_id);
/* In case we could not get an override ID with the exact same name as its linked reference,
* ensure we at least get a uniquely named override ID over the whole current Main data, to
@ -271,16 +277,14 @@ static ID *lib_override_library_create_from(Main *bmain,
id_sort_by_name(which_libbase(bmain, GS(local_id->name)), local_id, nullptr);
}
if (local_id == nullptr) {
return nullptr;
}
id_us_min(local_id);
/* TODO: Handle this properly in LIB_NO_MAIN case as well (i.e. resync case). Or offload to
* generic ID copy code? Would probably be better to have a version of #BKE_id_copy_ex that takes
* an extra `target_lib` parameter. */
local_id->lib = owner_library;
if ((lib_id_copy_flags & LIB_ID_CREATE_NO_MAIN) != 0 && owner_library == nullptr) {
/* In `NO_MAIN` case, generic `BKE_id_copy` code won't call this.
* In liboverride resync case however, the currently not-in-Main new IDs will be added back to
* Main later, so ensure that their linked dependencies and paths are properly handled here.
*
* NOTE: This is likely not the best place to do this. Ideally, #BKE_libblock_management_main_add
* e.g. should take care of this. But for the time being, this works and has been battle-proofed.
*/
if ((lib_id_copy_flags & LIB_ID_CREATE_NO_MAIN) != 0 && !ID_IS_LINKED(local_id)) {
lib_id_copy_ensure_local(bmain, reference_id, local_id, 0);
}

View File

@ -7,6 +7,7 @@
*/
#include <cstdlib>
#include <optional>
#include "MEM_guardedalloc.h"
@ -53,7 +54,11 @@ static void light_init_data(ID *id)
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void light_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void light_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Light *la_dst = (Light *)id_dst;
const Light *la_src = (const Light *)id_src;
@ -67,8 +72,11 @@ static void light_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
la_dst->nodetree = ntreeLocalize(la_src->nodetree);
}
else {
BKE_id_copy_ex(
bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
(ID *)la_src->nodetree,
(ID **)&la_dst->nodetree,
flag_private_id_data);
}
la_dst->nodetree->owner_id = &la_dst->id;
}

View File

@ -9,6 +9,8 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <optional>
#include <fmt/format.h>
#include "MEM_guardedalloc.h"
@ -50,7 +52,11 @@ static void linestyle_init_data(ID *id)
BKE_linestyle_geometry_modifier_add(linestyle, nullptr, LS_MODIFIER_SAMPLING);
}
static void linestyle_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void linestyle_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
FreestyleLineStyle *linestyle_dst = (FreestyleLineStyle *)id_dst;
const FreestyleLineStyle *linestyle_src = (const FreestyleLineStyle *)id_src;
@ -68,10 +74,11 @@ static void linestyle_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const
}
if (linestyle_src->nodetree) {
BKE_id_copy_ex(bmain,
(ID *)linestyle_src->nodetree,
(ID **)&linestyle_dst->nodetree,
flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
(ID *)linestyle_src->nodetree,
(ID **)&linestyle_dst->nodetree,
flag_private_id_data);
linestyle_dst->nodetree->owner_id = &linestyle_dst->id;
}

View File

@ -401,6 +401,7 @@ bool BKE_main_namemap_get_name(Main *bmain, ID *id, char *name, const bool do_un
* truncated name again. */
is_name_changed = true;
}
return is_name_changed;
}

View File

@ -8,6 +8,7 @@
#include <cstddef>
#include <cstring>
#include <optional>
#include "CLG_log.h"
@ -49,7 +50,11 @@
static CLG_LogRef LOG = {"bke.mask"};
static void mask_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void mask_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
Mask *mask_dst = (Mask *)id_dst;
const Mask *mask_src = (const Mask *)id_src;

View File

@ -9,6 +9,7 @@
#include <cmath>
#include <cstddef>
#include <cstring>
#include <optional>
#include "CLG_log.h"
@ -91,7 +92,11 @@ static void material_init_data(ID *id)
*((short *)id->name) = ID_MA;
}
static void material_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void material_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Material *material_dst = (Material *)id_dst;
const Material *material_src = (const Material *)id_src;
@ -105,10 +110,11 @@ static void material_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const
material_dst->nodetree = ntreeLocalize(material_src->nodetree);
}
else {
BKE_id_copy_ex(bmain,
(ID *)material_src->nodetree,
(ID **)&material_dst->nodetree,
flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
(ID *)material_src->nodetree,
(ID **)&material_dst->nodetree,
flag_private_id_data);
}
material_dst->nodetree->owner_id = &material_dst->id;
}

View File

@ -15,6 +15,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -64,7 +65,11 @@ static void metaball_init_data(ID *id)
MEMCPY_STRUCT_AFTER(metaball, DNA_struct_default_get(MetaBall), id);
}
static void metaball_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void metaball_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
MetaBall *metaball_dst = (MetaBall *)id_dst;
const MetaBall *metaball_src = (const MetaBall *)id_src;

View File

@ -6,6 +6,8 @@
* \ingroup bke
*/
#include <optional>
#include "MEM_guardedalloc.h"
/* Allow using deprecated functionality for .blend file I/O. */
@ -99,7 +101,11 @@ static void mesh_init_data(ID *id)
mesh->face_sets_color_seed = BLI_hash_int(BLI_time_now_seconds_i() & UINT_MAX);
}
static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void mesh_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Mesh *mesh_dst = reinterpret_cast<Mesh *>(id_dst);
const Mesh *mesh_src = reinterpret_cast<const Mesh *>(id_src);
@ -193,7 +199,7 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* TODO: Do we want to add flag to prevent this? */
if (mesh_src->key && (flag & LIB_ID_COPY_SHAPEKEY)) {
BKE_id_copy_ex(bmain, &mesh_src->key->id, (ID **)&mesh_dst->key, flag);
BKE_id_copy_in_lib(bmain, owner_library, &mesh_src->key->id, (ID **)&mesh_dst->key, flag);
/* XXX This is not nice, we need to make BKE_id_copy_ex fully re-entrant... */
mesh_dst->key->from = &mesh_dst->id;
}

View File

@ -9,6 +9,7 @@
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <optional>
#ifndef WIN32
# include <unistd.h>
@ -81,7 +82,11 @@ static void movie_clip_init_data(ID *id)
BKE_color_managed_colorspace_settings_init(&movie_clip->colorspace_settings);
}
static void movie_clip_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void movie_clip_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
MovieClip *movie_clip_dst = (MovieClip *)id_dst;
const MovieClip *movie_clip_src = (const MovieClip *)id_src;

View File

@ -14,6 +14,7 @@
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <optional>
/* Allow using deprecated functionality for .blend file I/O. */
#define DNA_DEPRECATED_ALLOW
@ -150,7 +151,11 @@ static void ntree_init_data(ID *id)
ntree_set_typeinfo(ntree, nullptr);
}
static void ntree_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int flag)
static void ntree_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
bNodeTree *ntree_dst = reinterpret_cast<bNodeTree *>(id_dst);
const bNodeTree *ntree_src = reinterpret_cast<const bNodeTree *>(id_src);

View File

@ -12,6 +12,7 @@
#include <cmath>
#include <cstdio>
#include <cstring>
#include <optional>
#include "CLG_log.h"
@ -188,7 +189,11 @@ static void object_init_data(ID *id)
animviz_settings_init(&ob->avs);
}
static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void object_copy_data(Main *bmain,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int flag)
{
Object *ob_dst = (Object *)id_dst;
const Object *ob_src = (const Object *)id_src;

View File

@ -8,6 +8,7 @@
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -100,7 +101,11 @@ static void palette_init_data(ID *id)
id_fake_user_set(&palette->id);
}
static void palette_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void palette_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
Palette *palette_dst = (Palette *)id_dst;
const Palette *palette_src = (const Palette *)id_src;
@ -172,6 +177,7 @@ IDTypeInfo IDType_ID_PAL = {
};
static void paint_curve_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)

View File

@ -13,6 +13,7 @@
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -99,6 +100,7 @@ static void particle_settings_init(ID *id)
}
static void particle_settings_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)

View File

@ -6,6 +6,8 @@
* \ingroup bke
*/
#include <optional>
#include "MEM_guardedalloc.h"
#include "DNA_defaults.h"
@ -68,6 +70,7 @@ static void pointcloud_init_data(ID *id)
}
static void pointcloud_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)

View File

@ -12,6 +12,7 @@
#include <cstddef>
#include <cstdio>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -251,7 +252,11 @@ static void scene_copy_markers(Scene *scene_dst, const Scene *scene_src, const i
}
}
static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void scene_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Scene *scene_dst = (Scene *)id_dst;
const Scene *scene_src = (const Scene *)id_src;
@ -266,10 +271,11 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* Master Collection */
if (scene_src->master_collection) {
BKE_id_copy_ex(bmain,
(ID *)scene_src->master_collection,
(ID **)&scene_dst->master_collection,
flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
reinterpret_cast<ID *>(scene_src->master_collection),
reinterpret_cast<ID **>(&scene_dst->master_collection),
flag_private_id_data);
scene_dst->master_collection->owner_id = &scene_dst->id;
}
@ -293,8 +299,11 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
BKE_keyingsets_copy(&(scene_dst->keyingsets), &(scene_src->keyingsets));
if (scene_src->nodetree) {
BKE_id_copy_ex(
bmain, (ID *)scene_src->nodetree, (ID **)&scene_dst->nodetree, flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
(ID *)scene_src->nodetree,
(ID **)&scene_dst->nodetree,
flag_private_id_data);
BKE_libblock_relink_ex(bmain,
scene_dst->nodetree,
(void *)(&scene_src->id),

View File

@ -8,6 +8,7 @@
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -58,7 +59,11 @@
static void sound_free_audio(bSound *sound);
static void sound_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void sound_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
bSound *sound_dst = (bSound *)id_dst;
const bSound *sound_src = (const bSound *)id_src;

View File

@ -9,6 +9,7 @@
#include <cstdlib> /* abort */
#include <cstring> /* strstr */
#include <cwctype>
#include <optional>
#include <sys/stat.h>
#include <sys/types.h>
@ -101,7 +102,11 @@ static void text_init_data(ID *id)
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void text_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void text_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
Text *text_dst = (Text *)id_dst;
const Text *text_src = (Text *)id_src;

View File

@ -10,6 +10,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -65,7 +66,11 @@ static void texture_init_data(ID *id)
BKE_imageuser_default(&texture->iuser);
}
static void texture_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void texture_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
Tex *texture_dst = (Tex *)id_dst;
const Tex *texture_src = (const Tex *)id_src;
@ -90,8 +95,11 @@ static void texture_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i
texture_dst->nodetree = ntreeLocalize(texture_src->nodetree);
}
else {
BKE_id_copy_ex(
bmain, (ID *)texture_src->nodetree, (ID **)&texture_dst->nodetree, flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
(ID *)texture_src->nodetree,
(ID **)&texture_dst->nodetree,
flag_private_id_data);
}
texture_dst->nodetree->owner_id = &texture_dst->id;
}

View File

@ -12,6 +12,7 @@
#include <cstdlib>
#include <cstring>
#include <cwctype>
#include <optional>
#include "CLG_log.h"
@ -82,7 +83,11 @@ static void vfont_init_data(ID *id)
}
}
static void vfont_copy_data(Main * /*bmain*/, ID *id_dst, const ID * /*id_src*/, const int flag)
static void vfont_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID * /*id_src*/,
const int flag)
{
VFont *vfont_dst = (VFont *)id_dst;

View File

@ -6,6 +6,8 @@
* \ingroup bke
*/
#include <optional>
#include "MEM_guardedalloc.h"
#include "DNA_defaults.h"
@ -148,7 +150,11 @@ static void volume_init_data(ID *id)
STRNCPY(volume->velocity_grid, "velocity");
}
static void volume_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
static void volume_copy_data(Main * /*bmain*/,
std::optional<Library *> /*owner_library*/,
ID *id_dst,
const ID *id_src,
const int /*flag*/)
{
Volume *volume_dst = (Volume *)id_dst;
const Volume *volume_src = (const Volume *)id_src;

View File

@ -9,6 +9,7 @@
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
@ -81,7 +82,11 @@ static void world_init_data(ID *id)
*
* \param flag: Copying options (see BKE_lib_id.hh's LIB_ID_COPY_... flags for more).
*/
static void world_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
static void world_copy_data(Main *bmain,
std::optional<Library *> owner_library,
ID *id_dst,
const ID *id_src,
const int flag)
{
World *wrld_dst = (World *)id_dst;
const World *wrld_src = (const World *)id_src;
@ -95,8 +100,11 @@ static void world_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
wrld_dst->nodetree = ntreeLocalize(wrld_src->nodetree);
}
else {
BKE_id_copy_ex(
bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag_private_id_data);
BKE_id_copy_in_lib(bmain,
owner_library,
(ID *)wrld_src->nodetree,
(ID **)&wrld_dst->nodetree,
flag_private_id_data);
}
wrld_dst->nodetree->owner_id = &wrld_dst->id;
}