Refactor/enhance ntreeMakeLocal().

Now using modern features from libquery/libremap areas.

Provides same kind of fixes/improvements as for BKE_object_make_local() (see rBd1a4ae3f395a6).
This commit is contained in:
Bastien Montagne 2016-07-10 16:55:55 +02:00
parent ad5918d278
commit 406309cd8c
3 changed files with 37 additions and 54 deletions

View File

@ -346,7 +346,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree);
struct bNodeTree *ntreeFromID(struct ID *id);
void ntreeMakeLocal(struct bNodeTree *ntree, bool id_in_mainlist);
void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist);
struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type);
bool ntreeHasType(const struct bNodeTree *ntree, int type);
bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup);

View File

@ -321,7 +321,7 @@ bool id_make_local(Main *bmain, ID *id, bool test)
if (!test) BKE_action_make_local((bAction *)id);
return true;
case ID_NT:
if (!test) ntreeMakeLocal((bNodeTree *)id, true);
if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true);
return true;
case ID_BR:
if (!test) BKE_brush_make_local(bmain, (Brush *)id);
@ -1469,7 +1469,7 @@ void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist)
ntree = ntreeFromID(id);
if (ntree) {
ntreeMakeLocal(ntree, false);
ntreeMakeLocal(bmain, ntree, false);
}
if (GS(id->name) == ID_OB) {

View File

@ -58,6 +58,8 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
@ -1948,70 +1950,51 @@ bNodeTree *ntreeFromID(ID *id)
}
}
static void extern_local_ntree(bNodeTree *ntree)
static int extern_local_ntree_callback(
void *UNUSED(user_data), struct ID *UNUSED(id_self), struct ID **id_pointer, int cd_flag)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->id) {
id_lib_extern(node->id);
}
/* We only tag usercounted ID usages as extern... Why? */
if ((cd_flag & IDWALK_USER) && *id_pointer) {
id_lib_extern(*id_pointer);
}
return IDWALK_RET_NOP;
}
void ntreeMakeLocal(bNodeTree *ntree, bool id_in_mainlist)
static void extern_local_ntree(bNodeTree *ntree)
{
Main *bmain = G.main;
bool lib = false, local = false;
BKE_library_foreach_ID_link(&ntree->id, extern_local_ntree_callback, NULL, 0);
}
void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist)
{
bool is_lib = false, is_local = false;
/* - only lib users: do nothing
* - only local users: set flag
* - mixed: make copy
*/
if (!ID_IS_LINKED_DATABLOCK(ntree)) return;
if (ntree->id.us == 1) {
id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
extern_local_ntree(ntree);
if (!ID_IS_LINKED_DATABLOCK(ntree)) {
return;
}
/* now check users of groups... again typedepending, callback... */
FOREACH_NODETREE(G.main, tntree, owner_id) {
bNode *node;
/* find if group is in tree */
for (node = tntree->nodes.first; node; node = node->next) {
if (node->id == (ID *)ntree) {
if (owner_id->lib)
lib = true;
else
local = true;
}
BKE_library_ID_test_usages(bmain, ntree, &is_local, &is_lib);
if (is_local) {
if (!is_lib) {
id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
extern_local_ntree(ntree);
}
else {
bNodeTree *ntree_new = ntreeCopyTree(bmain, ntree);
ntree_new->id.us = 0;
/* Remap paths of new ID using old library as base. */
BKE_id_lib_local_paths(bmain, ntree->id.lib, &ntree_new->id);
BKE_libblock_remap(bmain, ntree, ntree_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
} FOREACH_NODETREE_END
/* if all users are local, we simply make tree local */
if (local && !lib) {
id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist);
extern_local_ntree(ntree);
}
else if (local && lib) {
/* this is the mixed case, we copy the tree and assign it to local users */
bNodeTree *newtree = ntreeCopyTree(bmain, ntree);
newtree->id.us = 0;
FOREACH_NODETREE(bmain, tntree, owner_id) {
bNode *node;
/* find if group is in tree */
for (node = tntree->nodes.first; node; node = node->next) {
if (node->id == (ID *)ntree) {
if (owner_id->lib == NULL) {
node->id = (ID *)newtree;
id_us_plus(&newtree->id);
id_us_min(&ntree->id);
}
}
}
} FOREACH_NODETREE_END
}
}