Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / library.c
index 64c9ddb5b385bd2fd46a048ed2c41042fceb285f..978f1acefbaf5c730987da3f7afc5f54ef323519 100644 (file)
@@ -84,7 +84,6 @@
 #include "BKE_context.h"
 #include "BKE_curve.h"
 #include "BKE_depsgraph.h"
-#include "BKE_fcurve.h"
 #include "BKE_font.h"
 #include "BKE_global.h"
 #include "BKE_group.h"
@@ -92,7 +91,6 @@
 #include "BKE_idcode.h"
 #include "BKE_idprop.h"
 #include "BKE_image.h"
-#include "BKE_ipo.h"
 #include "BKE_key.h"
 #include "BKE_lamp.h"
 #include "BKE_lattice.h"
 #include "BKE_material.h"
 #include "BKE_main.h"
 #include "BKE_mball.h"
-#include "BKE_movieclip.h"
 #include "BKE_mask.h"
 #include "BKE_node.h"
 #include "BKE_object.h"
-#include "BKE_paint.h"
 #include "BKE_packedFile.h"
 #include "BKE_speaker.h"
-#include "BKE_sound.h"
-#include "BKE_screen.h"
 #include "BKE_scene.h"
 #include "BKE_text.h"
 #include "BKE_texture.h"
 #include "IMB_imbuf.h"
 #include "IMB_imbuf_types.h"
 
-#ifdef WITH_PYTHON
-#include "BPY_extern.h"
-#endif
-
 /* GS reads the memory pointed at in a specific ordering. 
  * only use this definition, makes little and big endian systems
  * work fine, in conjunction with MAKE_ID */
@@ -151,7 +141,7 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id)
 
 void id_lib_extern(ID *id)
 {
-       if (id) {
+       if (id && ID_IS_LINKED_DATABLOCK(id)) {
                BLI_assert(BKE_idcode_is_linkable(GS(id->name)));
                if (id->tag & LIB_TAG_INDIRECT) {
                        id->tag -= LIB_TAG_INDIRECT;
@@ -181,7 +171,6 @@ void id_us_ensure_real(ID *id)
        }
 }
 
-/* Unused currently... */
 void id_us_clear_real(ID *id)
 {
        if (id && (id->tag & LIB_TAG_EXTRAUSER)) {
@@ -231,9 +220,7 @@ void id_us_min(ID *id)
                if (id->us <= limit) {
                        printf("ID user decrement error: %s (from '%s'): %d <= %d\n",
                               id->name, id->lib ? id->lib->filepath : "[Main]", id->us, limit);
-                       /* We cannot assert here, because of how we 'delete' datablocks currently (setting their usercount to zero),
-                        * this is weak but it's how it works for now. */
-                       /* BLI_assert(0); */
+                       BLI_assert(0);
                        id->us = limit;
                }
                else {
@@ -263,9 +250,27 @@ void id_fake_user_clear(ID *id)
        }
 }
 
+static int id_expand_local_callback(
+        void *UNUSED(user_data), struct ID *UNUSED(id_self), struct ID **id_pointer, int UNUSED(cd_flag))
+{
+       if (*id_pointer) {
+               id_lib_extern(*id_pointer);
+       }
+
+       return IDWALK_RET_NOP;
+}
+
+/**
+ * Expand ID usages of given id as 'extern' (and no more indirect) linked data. Used by ID copy/make_local functions.
+ */
+void BKE_id_expand_local(ID *id)
+{
+       BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0);
+}
+
 /* calls the appropriate make_local method for the block, unless test. Returns true
  * if the block can be made local. */
-bool id_make_local(ID *id, bool test)
+bool id_make_local(Main *bmain, ID *id, bool test)
 {
        if (id->tag & LIB_TAG_INDIRECT)
                return false;
@@ -276,54 +281,45 @@ bool id_make_local(ID *id, bool test)
                case ID_LI:
                        return false; /* can't be linked */
                case ID_OB:
-                       if (!test) BKE_object_make_local((Object *)id);
+                       if (!test) BKE_object_make_local(bmain, (Object *)id);
                        return true;
                case ID_ME:
-                       if (!test) {
-                               BKE_mesh_make_local((Mesh *)id);
-                               BKE_key_make_local(((Mesh *)id)->key);
-                       }
+                       if (!test) BKE_mesh_make_local(bmain, (Mesh *)id);
                        return true;
                case ID_CU:
-                       if (!test) {
-                               BKE_curve_make_local((Curve *)id);
-                               BKE_key_make_local(((Curve *)id)->key);
-                       }
+                       if (!test) BKE_curve_make_local(bmain, (Curve *)id);
                        return true;
                case ID_MB:
-                       if (!test) BKE_mball_make_local((MetaBall *)id);
+                       if (!test) BKE_mball_make_local(bmain, (MetaBall *)id);
                        return true;
                case ID_MA:
-                       if (!test) BKE_material_make_local((Material *)id);
+                       if (!test) BKE_material_make_local(bmain, (Material *)id);
                        return true;
                case ID_TE:
-                       if (!test) BKE_texture_make_local((Tex *)id);
+                       if (!test) BKE_texture_make_local(bmain, (Tex *)id);
                        return true;
                case ID_IM:
-                       if (!test) BKE_image_make_local((Image *)id);
+                       if (!test) BKE_image_make_local(bmain, (Image *)id);
                        return true;
                case ID_LT:
-                       if (!test) {
-                               BKE_lattice_make_local((Lattice *)id);
-                               BKE_key_make_local(((Lattice *)id)->key);
-                       }
+                       if (!test) BKE_lattice_make_local(bmain, (Lattice *)id);
                        return true;
                case ID_LA:
-                       if (!test) BKE_lamp_make_local((Lamp *)id);
+                       if (!test) BKE_lamp_make_local(bmain, (Lamp *)id);
                        return true;
                case ID_CA:
-                       if (!test) BKE_camera_make_local((Camera *)id);
+                       if (!test) BKE_camera_make_local(bmain, (Camera *)id);
                        return true;
                case ID_SPK:
-                       if (!test) BKE_speaker_make_local((Speaker *)id);
+                       if (!test) BKE_speaker_make_local(bmain, (Speaker *)id);
                        return true;
                case ID_IP:
                        return false; /* deprecated */
                case ID_KE:
-                       if (!test) BKE_key_make_local((Key *)id);
+                       if (!test) BKE_key_make_local(bmain, (Key *)id);
                        return true;
                case ID_WO:
-                       if (!test) BKE_world_make_local((World *)id);
+                       if (!test) BKE_world_make_local(bmain, (World *)id);
                        return true;
                case ID_SCR:
                        return false; /* can't be linked */
@@ -336,16 +332,16 @@ bool id_make_local(ID *id, bool test)
                case ID_GR:
                        return false; /* not implemented */
                case ID_AR:
-                       if (!test) BKE_armature_make_local((bArmature *)id);
+                       if (!test) BKE_armature_make_local(bmain, (bArmature *)id);
                        return true;
                case ID_AC:
-                       if (!test) BKE_action_make_local((bAction *)id);
+                       if (!test) BKE_action_make_local(bmain, (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((Brush *)id);
+                       if (!test) BKE_brush_make_local(bmain, (Brush *)id);
                        return true;
                case ID_WM:
                        return false; /* can't be linked */
@@ -362,9 +358,11 @@ bool id_make_local(ID *id, bool test)
  * Invokes the appropriate copy method for the block and returns the result in
  * newid, unless test. Returns true if the block can be copied.
  */
-bool id_copy(ID *id, ID **newid, bool test)
+bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
 {
-       if (!test) *newid = NULL;
+       if (!test) {
+               *newid = NULL;
+       }
 
        /* conventions:
         * - make shallow copy, only this ID block
@@ -375,117 +373,86 @@ bool id_copy(ID *id, ID **newid, bool test)
                case ID_LI:
                        return false;  /* can't be copied from here */
                case ID_OB:
-                       if (!test) *newid = (ID *)BKE_object_copy((Object *)id);
+                       if (!test) *newid = (ID *)BKE_object_copy(bmain, (Object *)id);
                        return true;
                case ID_ME:
-                       if (!test) *newid = (ID *)BKE_mesh_copy((Mesh *)id);
+                       if (!test) *newid = (ID *)BKE_mesh_copy(bmain, (Mesh *)id);
                        return true;
                case ID_CU:
-                       if (!test) *newid = (ID *)BKE_curve_copy((Curve *)id);
+                       if (!test) *newid = (ID *)BKE_curve_copy(bmain, (Curve *)id);
                        return true;
                case ID_MB:
-                       if (!test) *newid = (ID *)BKE_mball_copy((MetaBall *)id);
+                       if (!test) *newid = (ID *)BKE_mball_copy(bmain, (MetaBall *)id);
                        return true;
                case ID_MA:
-                       if (!test) *newid = (ID *)BKE_material_copy((Material *)id);
+                       if (!test) *newid = (ID *)BKE_material_copy(bmain, (Material *)id);
                        return true;
                case ID_TE:
-                       if (!test) *newid = (ID *)BKE_texture_copy((Tex *)id);
+                       if (!test) *newid = (ID *)BKE_texture_copy(bmain, (Tex *)id);
                        return true;
                case ID_IM:
-                       if (!test) *newid = (ID *)BKE_image_copy(G.main, (Image *)id);
+                       if (!test) *newid = (ID *)BKE_image_copy(bmain, (Image *)id);
                        return true;
                case ID_LT:
-                       if (!test) *newid = (ID *)BKE_lattice_copy((Lattice *)id);
+                       if (!test) *newid = (ID *)BKE_lattice_copy(bmain, (Lattice *)id);
                        return true;
                case ID_LA:
-                       if (!test) *newid = (ID *)BKE_lamp_copy((Lamp *)id);
+                       if (!test) *newid = (ID *)BKE_lamp_copy(bmain, (Lamp *)id);
                        return true;
                case ID_SPK:
-                       if (!test) *newid = (ID *)BKE_speaker_copy((Speaker *)id);
+                       if (!test) *newid = (ID *)BKE_speaker_copy(bmain, (Speaker *)id);
                        return true;
                case ID_CA:
-                       if (!test) *newid = (ID *)BKE_camera_copy((Camera *)id);
+                       if (!test) *newid = (ID *)BKE_camera_copy(bmain, (Camera *)id);
                        return true;
                case ID_IP:
                        return false;  /* deprecated */
                case ID_KE:
-                       if (!test) *newid = (ID *)BKE_key_copy((Key *)id);
+                       if (!test) *newid = (ID *)BKE_key_copy(bmain, (Key *)id);
                        return true;
                case ID_WO:
-                       if (!test) *newid = (ID *)BKE_world_copy((World *)id);
+                       if (!test) *newid = (ID *)BKE_world_copy(bmain, (World *)id);
                        return true;
                case ID_SCR:
                        return false;  /* can't be copied from here */
                case ID_VF:
                        return false;  /* not implemented */
                case ID_TXT:
-                       if (!test) *newid = (ID *)BKE_text_copy(G.main, (Text *)id);
+                       if (!test) *newid = (ID *)BKE_text_copy(bmain, (Text *)id);
                        return true;
                case ID_SO:
                        return false;  /* not implemented */
                case ID_GR:
-                       if (!test) *newid = (ID *)BKE_group_copy((Group *)id);
+                       if (!test) *newid = (ID *)BKE_group_copy(bmain, (Group *)id);
                        return true;
                case ID_AR:
-                       if (!test) *newid = (ID *)BKE_armature_copy((bArmature *)id);
+                       if (!test) *newid = (ID *)BKE_armature_copy(bmain, (bArmature *)id);
                        return true;
                case ID_AC:
-                       if (!test) *newid = (ID *)BKE_action_copy((bAction *)id);
+                       if (!test) *newid = (ID *)BKE_action_copy(bmain, (bAction *)id);
                        return true;
                case ID_NT:
-                       if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id);
+                       if (!test) *newid = (ID *)ntreeCopyTree(bmain, (bNodeTree *)id);
                        return true;
                case ID_BR:
-                       if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id);
+                       if (!test) *newid = (ID *)BKE_brush_copy(bmain, (Brush *)id);
                        return true;
                case ID_WM:
                        return false;  /* can't be copied from here */
                case ID_GD:
-                       if (!test) *newid = (ID *)gpencil_data_duplicate((bGPdata *)id, false);
+                       if (!test) *newid = (ID *)gpencil_data_duplicate(bmain, (bGPdata *)id, false);
                        return true;
                case ID_MSK:
-                       if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id);
+                       if (!test) *newid = (ID *)BKE_mask_copy(bmain, (Mask *)id);
                        return true;
                case ID_LS:
-                       if (!test) *newid = (ID *)BKE_linestyle_copy(G.main, (FreestyleLineStyle *)id);
+                       if (!test) *newid = (ID *)BKE_linestyle_copy(bmain, (FreestyleLineStyle *)id);
                        return true;
        }
        
        return false;
 }
 
-bool id_unlink(ID *id, int test)
-{
-       Main *mainlib = G.main;
-       short type = GS(id->name);
-
-       switch (type) {
-               case ID_TXT:
-                       if (test) return true;
-                       BKE_text_unlink(mainlib, (Text *)id);
-                       break;
-               case ID_GR:
-                       if (test) return true;
-                       BKE_group_unlink(mainlib, (Group *)id);
-                       break;
-               case ID_OB:
-                       if (test) return true;
-                       BKE_object_unlink(mainlib, (Object *)id);
-                       break;
-       }
-
-       if (id->us == 0) {
-               if (test) return true;
-
-               BKE_libblock_free(mainlib, id);
-
-               return true;
-       }
-
-       return false;
-}
-
 bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
 {
        ID *newid = NULL;
@@ -494,7 +461,7 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
        if (id) {
                /* if property isn't editable, we're going to have an extra block hanging around until we save */
                if (RNA_property_editable(ptr, prop)) {
-                       if (id_copy(id, &newid, false) && newid) {
+                       if (id_copy(CTX_data_main(C), id, &newid, false) && newid) {
                                /* copy animation actions too */
                                BKE_animdata_copy_id_action(id);
                                /* us is 1 by convention, but RNA_property_pointer_set
@@ -665,7 +632,7 @@ void BKE_main_lib_objects_recalc_all(Main *bmain)
 
        /* flag for full recalc */
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
-               if (ob->id.lib) {
+               if (ID_IS_LINKED_DATABLOCK(ob)) {
                        DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
                }
        }
@@ -1013,7 +980,7 @@ void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action)
 }
 
 /* used everywhere in blenkernel */
-void *BKE_libblock_copy_ex(Main *bmain, ID *id)
+void *BKE_libblock_copy(Main *bmain, ID *id)
 {
        ID *idn;
        size_t idn_len;
@@ -1065,11 +1032,6 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
        return idn;
 }
 
-void *BKE_libblock_copy(ID *id)
-{
-       return BKE_libblock_copy_ex(G.main, id);
-}
-
 static int id_relink_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **id_pointer, const int cd_flag)
 {
        ID *id = *id_pointer;
@@ -1089,237 +1051,18 @@ static int id_relink_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **i
 
 void BKE_libblock_relink(ID *id)
 {
-       if (id->lib)
+       if (ID_IS_LINKED_DATABLOCK(id))
                return;
 
        BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0);
 }
 
-static void BKE_library_free(Library *lib)
+void BKE_library_free(Library *lib)
 {
        if (lib->packedfile)
                freePackedFile(lib->packedfile);
 }
 
-static BKE_library_free_window_manager_cb free_windowmanager_cb = NULL;
-
-void BKE_library_callback_free_window_manager_set(BKE_library_free_window_manager_cb func)
-{
-       free_windowmanager_cb = func;
-}
-
-static BKE_library_free_notifier_reference_cb free_notifier_reference_cb = NULL;
-
-void BKE_library_callback_free_notifier_reference_set(BKE_library_free_notifier_reference_cb func)
-{
-       free_notifier_reference_cb = func;
-}
-
-static BKE_library_free_editor_id_reference_cb free_editor_id_reference_cb = NULL;
-
-void BKE_library_callback_free_editor_id_reference_set(BKE_library_free_editor_id_reference_cb func)
-{
-       free_editor_id_reference_cb = func;
-}
-
-static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata)
-{
-       ChannelDriver *driver;
-       FCurve *fcu;
-
-       /* find the driver this belongs to and update it */
-       for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
-               driver = fcu->driver;
-               
-               if (driver) {
-                       DriverVar *dvar;
-                       for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
-                               DRIVER_TARGETS_USED_LOOPER(dvar) 
-                               {
-                                       if (dtar->id == userdata)
-                                               dtar->id = NULL;
-                               }
-                               DRIVER_TARGETS_LOOPER_END
-                       }
-               }
-       }
-}
-
-void BKE_libblock_free_data(Main *bmain, ID *id)
-{
-       if (id->properties) {
-               IDP_FreeProperty(id->properties);
-               MEM_freeN(id->properties);
-       }
-       
-       /* this ID may be a driver target! */
-       BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id);
-}
-
-/* used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c */
-void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
-{
-       ID *id = idv;
-       short type = GS(id->name);
-       ListBase *lb = which_libbase(bmain, type);
-
-       DAG_id_type_tag(bmain, type);
-
-#ifdef WITH_PYTHON
-       BPY_id_release(id);
-#endif
-
-       switch (type) {    /* GetShort from util.h */
-               case ID_SCE:
-                       BKE_scene_free((Scene *)id);
-                       break;
-               case ID_LI:
-                       BKE_library_free((Library *)id);
-                       break;
-               case ID_OB:
-                       BKE_object_free_ex((Object *)id, do_id_user);
-                       break;
-               case ID_ME:
-                       BKE_mesh_free((Mesh *)id, 1);
-                       break;
-               case ID_CU:
-                       BKE_curve_free((Curve *)id);
-                       break;
-               case ID_MB:
-                       BKE_mball_free((MetaBall *)id);
-                       break;
-               case ID_MA:
-                       BKE_material_free((Material *)id);
-                       break;
-               case ID_TE:
-                       BKE_texture_free((Tex *)id);
-                       break;
-               case ID_IM:
-                       BKE_image_free((Image *)id);
-                       break;
-               case ID_LT:
-                       BKE_lattice_free((Lattice *)id);
-                       break;
-               case ID_LA:
-                       BKE_lamp_free((Lamp *)id);
-                       break;
-               case ID_CA:
-                       BKE_camera_free((Camera *) id);
-                       break;
-               case ID_IP:
-                       BKE_ipo_free((Ipo *)id);
-                       break;
-               case ID_KE:
-                       BKE_key_free((Key *)id);
-                       break;
-               case ID_WO:
-                       BKE_world_free((World *)id);
-                       break;
-               case ID_SCR:
-                       BKE_screen_free((bScreen *)id);
-                       break;
-               case ID_VF:
-                       BKE_vfont_free((VFont *)id);
-                       break;
-               case ID_TXT:
-                       BKE_text_free((Text *)id);
-                       break;
-               case ID_SPK:
-                       BKE_speaker_free((Speaker *)id);
-                       break;
-               case ID_SO:
-                       BKE_sound_free((bSound *)id);
-                       break;
-               case ID_GR:
-                       BKE_group_free((Group *)id);
-                       break;
-               case ID_AR:
-                       BKE_armature_free((bArmature *)id);
-                       break;
-               case ID_AC:
-                       BKE_action_free((bAction *)id);
-                       break;
-               case ID_NT:
-                       ntreeFreeTree_ex((bNodeTree *)id, do_id_user);
-                       break;
-               case ID_BR:
-                       BKE_brush_free((Brush *)id);
-                       break;
-               case ID_WM:
-                       if (free_windowmanager_cb)
-                               free_windowmanager_cb(NULL, (wmWindowManager *)id);
-                       break;
-               case ID_GD:
-                       BKE_gpencil_free((bGPdata *)id);
-                       break;
-               case ID_MC:
-                       BKE_movieclip_free((MovieClip *)id);
-                       break;
-               case ID_MSK:
-                       BKE_mask_free(bmain, (Mask *)id);
-                       break;
-               case ID_LS:
-                       BKE_linestyle_free((FreestyleLineStyle *)id);
-                       break;
-               case ID_PAL:
-                       BKE_palette_free((Palette *)id);
-                       break;
-               case ID_PC:
-                       BKE_paint_curve_free((PaintCurve *)id);
-                       break;
-       }
-
-       /* avoid notifying on removed data */
-       BKE_main_lock(bmain);
-
-       if (free_notifier_reference_cb) {
-               free_notifier_reference_cb(id);
-       }
-
-       if (free_editor_id_reference_cb) {
-               free_editor_id_reference_cb(id);
-       }
-
-       BLI_remlink(lb, id);
-
-       BKE_libblock_free_data(bmain, id);
-       BKE_main_unlock(bmain);
-
-       MEM_freeN(id);
-}
-
-void BKE_libblock_free(Main *bmain, void *idv)
-{
-       BKE_libblock_free_ex(bmain, idv, true);
-}
-
-void BKE_libblock_free_us(Main *bmain, void *idv)      /* test users */
-{
-       ID *id = idv;
-       
-       id_us_min(id);
-
-       /* XXX This is a temp (2.77) hack so that we keep same behavior as in 2.76 regarding groups when deleting an object.
-        *     Since only 'user_one' usage of objects is groups, and only 'real user' usage of objects is scenes,
-        *     removing that 'user_one' tag when there is no more real (scene) users of an object ensures it gets
-        *     fully unlinked.
-        *     Otherwise, there is no real way to get rid of an object anymore - better handling of this is TODO.
-        */
-       if ((GS(id->name) == ID_OB) && (id->us == 1)) {
-               id_us_clear_real(id);
-       }
-
-       if (id->us == 0) {
-               switch (GS(id->name)) {
-                       case ID_OB:
-                               BKE_object_unlink(bmain, (Object *)id);
-                               break;
-               }
-               
-               BKE_libblock_free(bmain, id);
-       }
-}
-
 Main *BKE_main_new(void)
 {
        Main *bmain = MEM_callocN(sizeof(Main), "new main");
@@ -1522,7 +1265,7 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name)
        
        for (idtest = lb->first; idtest; idtest = idtest->next) {
                /* if idtest is not a lib */ 
-               if (id != idtest && idtest->lib == NULL) {
+               if (id != idtest && !ID_IS_LINKED_DATABLOCK(idtest)) {
                        /* do not test alphabetic! */
                        /* optimized */
                        if (idtest->name[2] == name[0]) {
@@ -1582,7 +1325,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name)
                for (idtest = lb->first; idtest; idtest = idtest->next) {
                        int nrtest;
                        if ( (id != idtest) &&
-                            (idtest->lib == NULL) &&
+                            !ID_IS_LINKED_DATABLOCK(idtest) &&
                             (*name == *(idtest->name + 2)) &&
                             STREQLEN(name, idtest->name + 2, left_len) &&
                             (BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len)
@@ -1664,7 +1407,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname)
        char name[MAX_ID_NAME - 2];
 
        /* if library, don't rename */
-       if (id->lib)
+       if (ID_IS_LINKED_DATABLOCK(id))
                return false;
 
        /* if no libdata given, look up based on ID */
@@ -1728,7 +1471,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) {
@@ -1769,7 +1512,7 @@ static void lib_indirect_test_id(ID *id, const Library *lib)
 #define LIBTAG(a) \
        if (a && a->id.lib) { a->id.tag &= ~LIB_TAG_INDIRECT; a->id.tag |= LIB_TAG_EXTERN; } (void)0
        
-       if (id->lib) {
+       if (ID_IS_LINKED_DATABLOCK(id)) {
                /* datablocks that were indirectly related are now direct links
                 * without this, appending data that has a link to other data will fail to write */
                if (lib && id->lib->parent == lib) {