Refactor: Remove `BKE_XXX_localize()`, in favor of using regular ID copying code.

Besides the NodeTree case (which remains unchanged), the localize code
is only used in one place (to generate previews of shading data-blocks).

This commit introduces a new `LIB_ID_CREATE_LOCAL` option for ID
creation/copying, which essentially implements the behavior of the
removed `BKE_XXX_localize()` functions into regular mainstream ID copy
code. When this option is set:
- new ID is tagged with `LIB_TAG_LOCALIZED`;
- Some ID copying callbacks have specific behaviors, mainly the root
  nodetree of shading IDs gets duplicated with specialized
  `ntreeLocalize()` function.

Note that I would not consider getting rid of `ntreeLocalize` for now,
this function is recursive, which should ideally never happen within ID
management copying code (this introduces all kind of complications).

No behavioral change expected from this commit.
This commit is contained in:
Bastien Montagne 2020-10-06 17:43:12 +02:00
parent 94f91827f8
commit 874cf52c10
11 changed files with 67 additions and 145 deletions

View File

@ -99,6 +99,12 @@ enum {
/** Do not tag new ID for update in depsgraph. */
LIB_ID_CREATE_NO_DEG_TAG = 1 << 8,
/** Very similar to #LIB_ID_CREATE_NO_MAIN, and should never be used with it (typically combined
* with #LIB_ID_CREATE_LOCALIZE or #LIB_ID_COPY_LOCALIZE in fact).
* It ensures that IDs created with it will get the #LIB_TAG_LOCALIZED tag, and uses some
* specific code in some copy cases (mostly for node trees). */
LIB_ID_CREATE_LOCAL = 1 << 9,
/* *** Specific options to some ID types or usages. *** */
/* *** May be ignored by unrelated ID copying functions. *** */
/** Object only, needed by make_local code. */

View File

@ -36,7 +36,6 @@ struct Main;
struct Light *BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
struct Light *BKE_light_copy(struct Main *bmain, const struct Light *la) ATTR_WARN_UNUSED_RESULT;
struct Light *BKE_light_localize(struct Light *la) ATTR_WARN_UNUSED_RESULT;
void BKE_light_eval(struct Depsgraph *depsgraph, struct Light *la);

View File

@ -54,7 +54,6 @@ void BKE_object_material_remap_calc(struct Object *ob_dst,
struct Material *BKE_material_add(struct Main *bmain, const char *name);
struct Material *BKE_gpencil_material_add(struct Main *bmain, const char *name);
struct Material *BKE_material_copy(struct Main *bmain, const struct Material *ma);
struct Material *BKE_material_localize(struct Material *ma);
void BKE_gpencil_material_attr_init(struct Material *ma);
/* UNUSED */

View File

@ -47,7 +47,6 @@ void BKE_texture_mtex_foreach_id(struct LibraryForeachIDData *data, struct MTex
void BKE_texture_default(struct Tex *tex);
struct Tex *BKE_texture_copy(struct Main *bmain, const struct Tex *tex);
struct Tex *BKE_texture_add(struct Main *bmain, const char *name);
struct Tex *BKE_texture_localize(struct Tex *tex);
void BKE_texture_type_set(struct Tex *tex, int type);
void BKE_texture_mtex_default(struct MTex *mtex);

View File

@ -31,7 +31,6 @@ struct Main;
struct World;
struct World *BKE_world_add(struct Main *bmain, const char *name);
struct World *BKE_world_localize(struct World *wrld);
void BKE_world_eval(struct Depsgraph *depsgraph, struct World *world);
#ifdef __cplusplus

View File

@ -1035,6 +1035,8 @@ void *BKE_libblock_alloc_notest(short type)
void *BKE_libblock_alloc(Main *bmain, 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 != NULL);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_LOCAL) == 0);
ID *id = BKE_libblock_alloc_notest(type);
@ -1045,6 +1047,9 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) {
id->tag |= LIB_TAG_NO_USER_REFCOUNT;
}
if (flag & LIB_ID_CREATE_LOCAL) {
id->tag |= LIB_TAG_LOCALIZED;
}
id->icon_id = 0;
*((short *)id->name) = type;
@ -1180,6 +1185,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_LOCAL) == 0);
if (!is_private_id_data) {
/* When we are handling private ID data, we might still want to manage usercounts, even
* though that ID data-block is actually outside of Main... */

View File

@ -81,13 +81,21 @@ static void light_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
{
Light *la_dst = (Light *)id_dst;
const Light *la_src = (const Light *)id_src;
const bool is_localized = (flag & LIB_ID_CREATE_LOCAL) != 0;
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
la_dst->curfalloff = BKE_curvemapping_copy(la_src->curfalloff);
if (la_src->nodetree) {
BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag_private_id_data);
if (is_localized) {
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);
}
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@ -219,33 +227,6 @@ Light *BKE_light_copy(Main *bmain, const Light *la)
return la_copy;
}
Light *BKE_light_localize(Light *la)
{
/* TODO(bastien): Replace with something like:
*
* Light *la_copy;
* BKE_id_copy_ex(bmain, &la->id, (ID **)&la_copy,
* LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT,
* false);
* return la_copy;
*
* NOTE: Only possible once nested node trees are fully converted to that too. */
Light *lan = BKE_libblock_copy_for_localize(&la->id);
lan->curfalloff = BKE_curvemapping_copy(la->curfalloff);
if (la->nodetree) {
lan->nodetree = ntreeLocalize(la->nodetree);
}
lan->preview = NULL;
lan->id.tag |= LIB_TAG_LOCALIZED;
return lan;
}
void BKE_light_eval(struct Depsgraph *depsgraph, Light *la)
{
DEG_debug_print_eval(depsgraph, __func__, la->id.name, la);

View File

@ -100,12 +100,20 @@ static void material_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const
Material *material_dst = (Material *)id_dst;
const Material *material_src = (const Material *)id_src;
const bool is_localized = (flag & LIB_ID_CREATE_LOCAL) != 0;
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
if (material_src->nodetree) {
BKE_id_copy_ex(
bmain, (ID *)material_src->nodetree, (ID **)&material_dst->nodetree, flag_private_id_data);
if (material_src->nodetree != NULL) {
if (is_localized) {
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);
}
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@ -116,7 +124,8 @@ static void material_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const
}
if (material_src->texpaintslot != NULL) {
material_dst->texpaintslot = MEM_dupallocN(material_src->texpaintslot);
/* TODO: Think we can also skip copying this data in the more generic `NO_MAIN` case? */
material_dst->texpaintslot = is_localized ? NULL : MEM_dupallocN(material_src->texpaintslot);
}
if (material_src->gp_style != NULL) {
@ -315,41 +324,6 @@ Material *BKE_material_copy(Main *bmain, const Material *ma)
return ma_copy;
}
/* XXX (see above) material copy without adding to main dbase */
Material *BKE_material_localize(Material *ma)
{
/* TODO(bastien): Replace with something like:
*
* Material *ma_copy;
* BKE_id_copy_ex(bmain, &ma->id, (ID **)&ma_copy,
* LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT,
* false);
* return ma_copy;
*
* NOTE: Only possible once nested node trees are fully converted to that too. */
Material *man = BKE_libblock_copy_for_localize(&ma->id);
man->texpaintslot = NULL;
man->preview = NULL;
if (ma->nodetree != NULL) {
man->nodetree = ntreeLocalize(ma->nodetree);
}
if (ma->gp_style != NULL) {
man->gp_style = MEM_dupallocN(ma->gp_style);
}
BLI_listbase_clear(&man->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
man->id.tag |= LIB_TAG_LOCALIZED;
return man;
}
Material ***BKE_object_material_array_p(Object *ob)
{
if (ob->type == OB_MESH) {

View File

@ -87,6 +87,7 @@ static void texture_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i
Tex *texture_dst = (Tex *)id_dst;
const Tex *texture_src = (const Tex *)id_src;
const bool is_localized = (flag & LIB_ID_CREATE_LOCAL) != 0;
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
@ -101,8 +102,14 @@ static void texture_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const i
if (texture_src->nodetree->execdata) {
ntreeTexEndExecTree(texture_src->nodetree->execdata);
}
BKE_id_copy_ex(
bmain, (ID *)texture_src->nodetree, (ID **)&texture_dst->nodetree, flag_private_id_data);
if (is_localized) {
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);
}
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@ -455,40 +462,6 @@ Tex *BKE_texture_copy(Main *bmain, const Tex *tex)
return tex_copy;
}
/* texture copy without adding to main dbase */
Tex *BKE_texture_localize(Tex *tex)
{
/* TODO(bastien): Replace with something like:
*
* Tex *tex_copy;
* BKE_id_copy_ex(bmain, &tex->id, (ID **)&tex_copy,
* LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT,
* false);
* return tex_copy;
*
* NOTE: Only possible once nested node trees are fully converted to that too. */
Tex *texn;
texn = BKE_libblock_copy_for_localize(&tex->id);
/* image texture: texture_free_data also doesn't decrease */
if (texn->coba) {
texn->coba = MEM_dupallocN(texn->coba);
}
texn->preview = NULL;
if (tex->nodetree) {
texn->nodetree = ntreeLocalize(tex->nodetree);
}
texn->id.tag |= LIB_TAG_LOCALIZED;
return texn;
}
/* ------------------------------------------------------------------------- */
Tex *give_current_linestyle_texture(FreestyleLineStyle *linestyle)

View File

@ -99,12 +99,19 @@ static void world_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
{
World *wrld_dst = (World *)id_dst;
const World *wrld_src = (const World *)id_src;
const bool is_localized = (flag & LIB_ID_CREATE_LOCAL) != 0;
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
if (wrld_src->nodetree) {
BKE_id_copy_ex(
bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag_private_id_data);
if (is_localized) {
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);
}
}
BLI_listbase_clear(&wrld_dst->gpumaterial);
@ -210,36 +217,6 @@ World *BKE_world_add(Main *bmain, const char *name)
return wrld;
}
World *BKE_world_localize(World *wrld)
{
/* TODO(bastien): Replace with something like:
*
* World *wrld_copy;
* BKE_id_copy_ex(bmain, &wrld->id, (ID **)&wrld_copy,
* LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_NO_USER_REFCOUNT,
* false);
* return wrld_copy;
*
* NOTE: Only possible once nested node trees are fully converted to that too. */
World *wrldn;
wrldn = BKE_libblock_copy_for_localize(&wrld->id);
if (wrld->nodetree) {
wrldn->nodetree = ntreeLocalize(wrld->nodetree);
}
wrldn->preview = NULL;
BLI_listbase_clear(&wrldn->gpumaterial);
BLI_listbase_clear((ListBase *)&wrldn->drawdata);
wrldn->id.tag |= LIB_TAG_LOCALIZED;
return wrldn;
}
void BKE_world_eval(struct Depsgraph *depsgraph, World *world)
{
DEG_debug_print_eval(depsgraph, __func__, world->id.name, world);

View File

@ -325,7 +325,13 @@ static World *preview_get_localized_world(ShaderPreview *sp, World *world)
if (sp->worldcopy != NULL) {
return sp->worldcopy;
}
sp->worldcopy = BKE_world_localize(world);
ID *id_copy;
BKE_id_copy_ex(NULL,
&world->id,
&id_copy,
LIB_ID_CREATE_LOCAL | LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
sp->worldcopy = (World *)id_copy;
BLI_addtail(&sp->pr_main->worlds, sp->worldcopy);
return sp->worldcopy;
}
@ -339,13 +345,16 @@ static ID *duplicate_ids(ID *id)
switch (GS(id->name)) {
case ID_MA:
return (ID *)BKE_material_localize((Material *)id);
case ID_TE:
return (ID *)BKE_texture_localize((Tex *)id);
case ID_LA:
return (ID *)BKE_light_localize((Light *)id);
case ID_WO:
return (ID *)BKE_world_localize((World *)id);
case ID_WO: {
ID *id_copy;
BKE_id_copy_ex(NULL,
id,
&id_copy,
LIB_ID_CREATE_LOCAL | LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
return id_copy;
}
case ID_IM:
case ID_BR:
case ID_SCR: