Core: support localizing data-block without owner ID
Previously, the owner-id on localized node trees, like the one created in `GPU_material_from_nodetree` would have `bNodeTree::owner_id` set, even though they were independent. The leads to asserts when using `BKE_id_owner_get` on the localized node tree. The `node_tree_localize` already took a `ID *new_owner_id` parameter. However, if it was `nullptr` it was ignored instead actually clearing the `owner_id`. This patch changes the parameter to `std::optional<ID *> new_owner_id`. Now, `std::nullopt` means that the value is ignored and when `nullptr` is passed in, the `owner_id` will be cleared on the localized tree. Since `node_tree_localize` indirectly uses other functions, the same function signature change is done in `BKE_libblock_copy_in_lib` and `BKE_id_copy_in_lib`. The callers have been updated to pass in `nullopt` instead of `nullptr`. Pull Request: https://projects.blender.org/blender/blender/pulls/133002
This commit is contained in:
@@ -231,12 +231,12 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int orig_fla
|
||||
* 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).
|
||||
* \param new_owner_id: When copying an embedded ID, the owner ID of the new copy. Should be
|
||||
* `nullptr` for regular ID copying, or in case the owner ID is not (yet) known.
|
||||
* `nullopt` for regular ID copying, or in case the owner ID is not (yet) known.
|
||||
*/
|
||||
void BKE_libblock_copy_in_lib(Main *bmain,
|
||||
std::optional<Library *> owner_library,
|
||||
const ID *id,
|
||||
const ID *new_owner_id,
|
||||
std::optional<const ID *> new_owner_id,
|
||||
ID **new_id_p,
|
||||
int orig_flag);
|
||||
|
||||
@@ -612,12 +612,12 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag);
|
||||
* 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).
|
||||
* \param new_owner_id: When copying an embedded ID, the owner ID of the new copy. Should be
|
||||
* `nullptr` for regular ID copying, or in case the owner ID is not (yet) known.
|
||||
* `nullopt` for regular ID copying, or in case the owner ID is not (yet) known.
|
||||
*/
|
||||
struct ID *BKE_id_copy_in_lib(Main *bmain,
|
||||
std::optional<Library *> owner_library,
|
||||
const ID *id,
|
||||
const ID *new_owner_id,
|
||||
std::optional<const ID *> new_owner_id,
|
||||
ID **new_id_p,
|
||||
int flag);
|
||||
/**
|
||||
|
||||
@@ -587,10 +587,10 @@ void node_tree_set_output(bNodeTree *ntree);
|
||||
/**
|
||||
* Returns localized tree for execution in threads.
|
||||
*
|
||||
* \param new_owner_id: the owner ID of the localized nodetree, may be null if unknown or
|
||||
* \param new_owner_id: the owner ID of the localized nodetree, may be nullopt if unknown or
|
||||
* irrelevant.
|
||||
*/
|
||||
bNodeTree *node_tree_localize(bNodeTree *ntree, ID *new_owner_id);
|
||||
bNodeTree *node_tree_localize(bNodeTree *ntree, std::optional<ID *> new_owner_id);
|
||||
|
||||
/**
|
||||
* This is only direct data, tree itself should have been written.
|
||||
|
||||
@@ -381,14 +381,14 @@ AnimData *BKE_animdata_copy_in_lib(Main *bmain,
|
||||
BKE_id_copy_in_lib(bmain,
|
||||
owner_library,
|
||||
reinterpret_cast<ID *>(dadt->action),
|
||||
nullptr,
|
||||
std::nullopt,
|
||||
nullptr,
|
||||
id_copy_flag));
|
||||
dadt->tmpact = reinterpret_cast<bAction *>(
|
||||
BKE_id_copy_in_lib(bmain,
|
||||
owner_library,
|
||||
reinterpret_cast<ID *>(dadt->tmpact),
|
||||
nullptr,
|
||||
std::nullopt,
|
||||
nullptr,
|
||||
id_copy_flag));
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
@@ -1794,7 +1795,7 @@ ID *PartialWriteContext::id_add_copy(const ID *id, const bool regenerate_session
|
||||
const int copy_flags = (LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT |
|
||||
/* NOTE: Could make this an option if needed in the future */
|
||||
LIB_ID_COPY_ASSET_METADATA);
|
||||
ctx_root_id = BKE_id_copy_in_lib(nullptr, id->lib, id, nullptr, nullptr, copy_flags);
|
||||
ctx_root_id = BKE_id_copy_in_lib(nullptr, id->lib, id, std::nullopt, nullptr, copy_flags);
|
||||
ctx_root_id->tag |= ID_TAG_TEMP_MAIN;
|
||||
if (regenerate_session_uid) {
|
||||
/* Calling #BKE_lib_libblock_session_uid_renew is not needed here, copying already generated a
|
||||
|
||||
@@ -2949,8 +2949,12 @@ static void legacy_gpencil_sanitize_annotations(Main &bmain)
|
||||
/* Legacy GP data also used by objects. Create the duplicate of legacy GPv2 data for
|
||||
* annotations, if not yet done. */
|
||||
if (!new_annotation_gpd) {
|
||||
new_annotation_gpd = reinterpret_cast<bGPdata *>(BKE_id_copy_in_lib(
|
||||
&bmain, legacy_gpd->id.lib, &legacy_gpd->id, nullptr, nullptr, LIB_ID_COPY_DEFAULT));
|
||||
new_annotation_gpd = reinterpret_cast<bGPdata *>(BKE_id_copy_in_lib(&bmain,
|
||||
legacy_gpd->id.lib,
|
||||
&legacy_gpd->id,
|
||||
std::nullopt,
|
||||
nullptr,
|
||||
LIB_ID_COPY_DEFAULT));
|
||||
new_annotation_gpd->flag |= GP_DATA_ANNOTATIONS;
|
||||
id_us_min(&new_annotation_gpd->id);
|
||||
annotations_gpv2.add_overwrite(legacy_gpd, new_annotation_gpd);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
@@ -656,7 +657,7 @@ bool BKE_id_copy_is_allowed(const ID *id)
|
||||
ID *BKE_id_copy_in_lib(Main *bmain,
|
||||
std::optional<Library *> owner_library,
|
||||
const ID *id,
|
||||
const ID *new_owner_id,
|
||||
std::optional<const ID *> new_owner_id,
|
||||
ID **new_id_p,
|
||||
const int flag)
|
||||
{
|
||||
@@ -759,12 +760,12 @@ ID *BKE_id_copy_in_lib(Main *bmain,
|
||||
|
||||
ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, const int flag)
|
||||
{
|
||||
return BKE_id_copy_in_lib(bmain, std::nullopt, id, nullptr, new_id_p, flag);
|
||||
return BKE_id_copy_in_lib(bmain, std::nullopt, id, std::nullopt, new_id_p, flag);
|
||||
}
|
||||
|
||||
ID *BKE_id_copy(Main *bmain, const ID *id)
|
||||
{
|
||||
return BKE_id_copy_in_lib(bmain, std::nullopt, id, nullptr, nullptr, LIB_ID_COPY_DEFAULT);
|
||||
return BKE_id_copy_in_lib(bmain, std::nullopt, id, std::nullopt, nullptr, LIB_ID_COPY_DEFAULT);
|
||||
}
|
||||
|
||||
ID *BKE_id_copy_for_duplicate(Main *bmain,
|
||||
@@ -1510,7 +1511,7 @@ void *BKE_id_new_nomain(const short type, const char *name)
|
||||
void BKE_libblock_copy_in_lib(Main *bmain,
|
||||
std::optional<Library *> owner_library,
|
||||
const ID *id,
|
||||
const ID *new_owner_id,
|
||||
std::optional<const ID *> new_owner_id,
|
||||
ID **new_id_p,
|
||||
const int orig_flag)
|
||||
{
|
||||
@@ -1585,11 +1586,17 @@ void BKE_libblock_copy_in_lib(Main *bmain,
|
||||
* is given. In some cases (e.g. depsgraph), this is important for later remapping to work
|
||||
* properly.
|
||||
*/
|
||||
if (new_owner_id) {
|
||||
if (new_owner_id.has_value()) {
|
||||
const IDTypeInfo *idtype = BKE_idtype_get_info_from_id(new_id);
|
||||
BLI_assert(idtype->owner_pointer_get != nullptr);
|
||||
ID **owner_id_pointer = idtype->owner_pointer_get(new_id, false);
|
||||
*owner_id_pointer = const_cast<ID *>(new_owner_id);
|
||||
if (owner_id_pointer) {
|
||||
*owner_id_pointer = const_cast<ID *>(*new_owner_id);
|
||||
if (*new_owner_id == nullptr) {
|
||||
/* If the new id does not have an owner, it's also not embedded. */
|
||||
new_id->flag &= ~ID_FLAG_EMBEDDED_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* We do not want any handling of user-count in code duplicating the data here, we do that all
|
||||
@@ -1647,14 +1654,14 @@ void BKE_libblock_copy_in_lib(Main *bmain,
|
||||
|
||||
void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **new_id_p, const int orig_flag)
|
||||
{
|
||||
BKE_libblock_copy_in_lib(bmain, std::nullopt, id, nullptr, new_id_p, orig_flag);
|
||||
BKE_libblock_copy_in_lib(bmain, std::nullopt, id, std::nullopt, new_id_p, orig_flag);
|
||||
}
|
||||
|
||||
void *BKE_libblock_copy(Main *bmain, const ID *id)
|
||||
{
|
||||
ID *idn = nullptr;
|
||||
|
||||
BKE_libblock_copy_in_lib(bmain, std::nullopt, id, nullptr, &idn, 0);
|
||||
BKE_libblock_copy_in_lib(bmain, std::nullopt, id, std::nullopt, &idn, 0);
|
||||
|
||||
return idn;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
|
||||
#include "CLG_log.h"
|
||||
@@ -266,7 +267,7 @@ static ID *lib_override_library_create_from(Main *bmain,
|
||||
ID *local_id = BKE_id_copy_in_lib(bmain,
|
||||
owner_library,
|
||||
reference_id,
|
||||
nullptr,
|
||||
std::nullopt,
|
||||
nullptr,
|
||||
(LIB_ID_COPY_DEFAULT | LIB_ID_COPY_NO_LIB_OVERRIDE |
|
||||
LIB_ID_COPY_NO_LIB_OVERRIDE_LOCAL_DATA_FLAG |
|
||||
|
||||
@@ -3764,7 +3764,7 @@ void node_tree_node_flag_set(const bNodeTree *ntree, const int flag, const bool
|
||||
}
|
||||
}
|
||||
|
||||
bNodeTree *node_tree_localize(bNodeTree *ntree, ID *new_owner_id)
|
||||
bNodeTree *node_tree_localize(bNodeTree *ntree, std::optional<ID *> new_owner_id)
|
||||
{
|
||||
if (ntree == nullptr) {
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user