Refactor/enhance ntreeMakeLocal().
authorBastien Montagne <montagne29@wanadoo.fr>
Sun, 10 Jul 2016 14:55:55 +0000 (16:55 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Sun, 10 Jul 2016 15:14:45 +0000 (17:14 +0200)
Now using modern features from libquery/libremap areas.

Provides same kind of fixes/improvements as for BKE_object_make_local() (see rBd1a4ae3f395a6).

source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/node.c

index c5d10441ebecb77ce9ae98c00757b89aed22f882..b44cb226f0d15a83ce81217dc1a6dac3da4fe545 100644 (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);
index 5f548b45fb1aca5010e1b097081141799e8b3fbc..d5b9e5ee4fcdefaec0e820b6f9c8a5b671b9e4ac 100644 (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) {
index aaba5dff7e41028709a5be660f6352b586d7639d..b18827221620da6697552ff786bff56b7cd01316 100644 (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;
+}
+
+static void extern_local_ntree(bNodeTree *ntree)
+{
+       BKE_library_foreach_ID_link(&ntree->id, extern_local_ntree_callback, NULL, 0);
 }
 
-void ntreeMakeLocal(bNodeTree *ntree, bool id_in_mainlist)
+void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist)
 {
-       Main *bmain = G.main;
-       bool lib = false, local = false;
+       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
        }
 }