Merge branch 'master' into blender2.8
[blender.git] / source / blender / windowmanager / intern / wm_files_link.c
index fb611290aa56bdeb9daefa8054578b76335fa98d..a33df1bc1f2d307af1584c8a08c53af3d5074241 100644 (file)
@@ -59,7 +59,7 @@
 #include "BLO_readfile.h"
 
 #include "BKE_context.h"
 #include "BLO_readfile.h"
 
 #include "BKE_context.h"
-#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_library_remap.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_library_remap.h"
 #include "BKE_global.h"
@@ -69,6 +69,8 @@
 
 #include "BKE_idcode.h"
 
 
 #include "BKE_idcode.h"
 
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
 
 #include "IMB_colormanagement.h"
 
 
 #include "IMB_colormanagement.h"
 
@@ -131,8 +133,8 @@ static short wm_link_append_flag(wmOperator *op)
 
        if (RNA_boolean_get(op->ptr, "autoselect"))
                flag |= FILE_AUTOSELECT;
 
        if (RNA_boolean_get(op->ptr, "autoselect"))
                flag |= FILE_AUTOSELECT;
-       if (RNA_boolean_get(op->ptr, "active_layer"))
-               flag |= FILE_ACTIVELAY;
+       if (RNA_boolean_get(op->ptr, "active_collection"))
+               flag |= FILE_ACTIVE_COLLECTION;
        if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop))
                flag |= FILE_RELPATH;
        if (RNA_boolean_get(op->ptr, "link"))
        if ((prop = RNA_struct_find_property(op->ptr, "relative_path")) && RNA_property_boolean_get(op->ptr, prop))
                flag |= FILE_RELPATH;
        if (RNA_boolean_get(op->ptr, "link"))
@@ -211,7 +213,8 @@ static WMLinkAppendDataItem *wm_link_append_data_item_add(
        return item;
 }
 
        return item;
 }
 
-static void wm_link_do(WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, View3D *v3d)
+static void wm_link_do(
+        WMLinkAppendData *lapp_data, ReportList *reports, Main *bmain, Scene *scene, ViewLayer *view_layer)
 {
        Main *mainl;
        BlendHandle *bh;
 {
        Main *mainl;
        BlendHandle *bh;
@@ -258,7 +261,7 @@ static void wm_link_do(WMLinkAppendData *lapp_data, ReportList *reports, Main *b
                                continue;
                        }
 
                                continue;
                        }
 
-                       new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, scene, v3d);
+                       new_id = BLO_library_link_named_part_ex(mainl, &bh, item->idcode, item->name, flag, scene, view_layer);
 
                        if (new_id) {
                                /* If the link is successful, clear item's libs 'todo' flags.
 
                        if (new_id) {
                                /* If the link is successful, clear item's libs 'todo' flags.
@@ -268,15 +271,50 @@ static void wm_link_do(WMLinkAppendData *lapp_data, ReportList *reports, Main *b
                        }
                }
 
                        }
                }
 
-               BLO_library_link_end(mainl, &bh, flag, scene, v3d);
+               BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
                BLO_blendhandle_close(bh);
        }
 }
 
                BLO_blendhandle_close(bh);
        }
 }
 
+/**
+ * Check if an item defined by \a name and \a group can be appended/linked.
+ *
+ * \param reports: Optionally report an error when an item can't be appended/linked.
+ */
+static bool wm_link_append_item_poll(
+        ReportList *reports, const char *path, const char *group, const char *name, const bool do_append)
+{
+       short idcode;
+
+       if (!group || !name) {
+               printf("skipping %s\n", path);
+               return false;
+       }
+
+       idcode = BKE_idcode_from_name(group);
+
+       /* XXX For now, we do a nasty exception for workspace, forbid linking them.
+        *     Not nice, ultimately should be solved! */
+       if (!BKE_idcode_is_linkable(idcode) && (do_append || idcode != ID_WS)) {
+               if (reports) {
+                       if (do_append) {
+                               BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't append data-block '%s' of type '%s'", name, group);
+                       }
+                       else {
+                               BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "Can't link data-block '%s' of type '%s'", name, group);
+                       }
+               }
+               return false;
+       }
+
+       return true;
+}
+
 static int wm_link_append_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
 static int wm_link_append_exec(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
        PropertyRNA *prop;
        WMLinkAppendData *lapp_data;
        char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
        PropertyRNA *prop;
        WMLinkAppendData *lapp_data;
        char path[FILE_MAX_LIBEXTRA], root[FILE_MAXDIR], libname[FILE_MAX_LIBEXTRA], relname[FILE_MAX];
@@ -319,6 +357,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
        }
 
        short flag = wm_link_append_flag(op);
        }
 
        short flag = wm_link_append_flag(op);
+       const bool do_append = (flag & FILE_LINK) == 0;
 
        /* sanity checks for flag */
        if (scene && scene->id.lib) {
 
        /* sanity checks for flag */
        if (scene && scene->id.lib) {
@@ -332,8 +371,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
 
        /* from here down, no error returns */
 
 
        /* from here down, no error returns */
 
-       if (scene && RNA_boolean_get(op->ptr, "autoselect")) {
-               BKE_scene_base_deselect_all(scene);
+       if (view_layer && RNA_boolean_get(op->ptr, "autoselect")) {
+               BKE_view_layer_base_deselect_all(view_layer);
        }
        
        /* tag everything, all untagged data can be made local
        }
        
        /* tag everything, all untagged data can be made local
@@ -356,7 +395,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
                        BLI_join_dirfile(path, sizeof(path), root, relname);
 
                        if (BLO_library_path_explode(path, libname, &group, &name)) {
                        BLI_join_dirfile(path, sizeof(path), root, relname);
 
                        if (BLO_library_path_explode(path, libname, &group, &name)) {
-                               if (!group || !name) {
+                               if (!wm_link_append_item_poll(NULL, path, group, name, do_append)) {
                                        continue;
                                }
 
                                        continue;
                                }
 
@@ -377,8 +416,8 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
 
                        if (BLO_library_path_explode(path, libname, &group, &name)) {
                                WMLinkAppendDataItem *item;
 
                        if (BLO_library_path_explode(path, libname, &group, &name)) {
                                WMLinkAppendDataItem *item;
-                               if (!group || !name) {
-                                       printf("skipping %s\n", path);
+
+                               if (!wm_link_append_item_poll(op->reports, path, group, name, do_append)) {
                                        continue;
                                }
 
                                        continue;
                                }
 
@@ -409,7 +448,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
        /* XXX We'd need re-entrant locking on Main for this to work... */
        /* BKE_main_lock(bmain); */
 
        /* XXX We'd need re-entrant locking on Main for this to work... */
        /* BKE_main_lock(bmain); */
 
-       wm_link_do(lapp_data, op->reports, bmain, scene, CTX_wm_view3d(C));
+       wm_link_do(lapp_data, op->reports, bmain, scene, view_layer);
 
        /* BKE_main_unlock(bmain); */
 
 
        /* BKE_main_unlock(bmain); */
 
@@ -418,7 +457,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
        IMB_colormanagement_check_file_config(bmain);
 
        /* append, rather than linking */
        IMB_colormanagement_check_file_config(bmain);
 
        /* append, rather than linking */
-       if ((flag & FILE_LINK) == 0) {
+       if (do_append) {
                const bool set_fake = RNA_boolean_get(op->ptr, "set_fake");
                const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive");
 
                const bool set_fake = RNA_boolean_get(op->ptr, "set_fake");
                const bool use_recursive = RNA_boolean_get(op->ptr, "use_recursive");
 
@@ -449,13 +488,17 @@ static int wm_link_append_exec(bContext *C, wmOperator *op)
         * link into other scenes from this blend file */
        BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
 
         * link into other scenes from this blend file */
        BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
 
+       /* TODO(sergey): Use proper flag for tagging here. */
+
+       /* TODO (dalai): Temporary solution!
+        * Ideally we only need to tag the new objects themselves, not the scene. This way we'll avoid flush of
+        * collection properties to all objects and limit update to the particular object only.
+        * But afraid first we need to change collection evaluation in DEG according to depsgraph manifesto.
+        */
+       DEG_id_tag_update(&scene->id, 0);
+
        /* recreate dependency graph to include new objects */
        /* recreate dependency graph to include new objects */
-       if (scene) {
-               DAG_scene_relations_rebuild(bmain, scene);
-       }
-       
-       /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
-       GPU_materials_free();
+       DEG_relations_tag_update(bmain);
 
        /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
        BLI_strncpy(G.lib, root, FILE_MAX);
 
        /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */
        BLI_strncpy(G.lib, root, FILE_MAX);
@@ -477,8 +520,8 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
        prop = RNA_def_boolean(ot->srna, "autoselect", true,
                               "Select", "Select new objects");
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
        prop = RNA_def_boolean(ot->srna, "autoselect", true,
                               "Select", "Select new objects");
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
-       prop = RNA_def_boolean(ot->srna, "active_layer", true,
-                              "Active Layer", "Put new objects on the active layer");
+       prop = RNA_def_boolean(ot->srna, "active_collection", true,
+                              "Active Collection", "Put new objects on the active collection");
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
        prop = RNA_def_boolean(ot->srna, "instance_groups", is_link,
                               "Instance Groups", "Create Dupli-Group instances for each group");
        RNA_def_property_flag(prop, PROP_SKIP_SAVE);
        prop = RNA_def_boolean(ot->srna, "instance_groups", is_link,
                               "Instance Groups", "Create Dupli-Group instances for each group");
@@ -558,7 +601,7 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN
 }
 
 static void lib_relocate_do(
 }
 
 static void lib_relocate_do(
-        Main *bmain, Scene *scene,
+        Main *bmain,
         Library *library, WMLinkAppendData *lapp_data, ReportList *reports, const bool do_reload)
 {
        ListBase *lbarray[MAX_LIBARRAY];
         Library *library, WMLinkAppendData *lapp_data, ReportList *reports, const bool do_reload)
 {
        ListBase *lbarray[MAX_LIBARRAY];
@@ -748,10 +791,7 @@ static void lib_relocate_do(
        BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
 
        /* recreate dependency graph to include new objects */
        BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
 
        /* recreate dependency graph to include new objects */
-       DAG_scene_relations_rebuild(bmain, scene);
-
-       /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */
-       GPU_materials_free();
+       DEG_relations_tag_update(bmain);
 }
 
 void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
 }
 
 void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
@@ -771,7 +811,7 @@ void WM_lib_reload(Library *lib, bContext *C, ReportList *reports)
 
        wm_link_append_data_library_add(lapp_data, lib->filepath);
 
 
        wm_link_append_data_library_add(lapp_data, lib->filepath);
 
-       lib_relocate_do(CTX_data_main(C), CTX_data_scene(C), lib, lapp_data, reports, true);
+       lib_relocate_do(CTX_data_main(C), lib, lapp_data, reports, true);
 
        wm_link_append_data_free(lapp_data);
 
 
        wm_link_append_data_free(lapp_data);
 
@@ -788,7 +828,6 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
 
        if (lib) {
                Main *bmain = CTX_data_main(C);
 
        if (lib) {
                Main *bmain = CTX_data_main(C);
-               Scene *scene = CTX_data_scene(C);
                PropertyRNA *prop;
                WMLinkAppendData *lapp_data;
 
                PropertyRNA *prop;
                WMLinkAppendData *lapp_data;
 
@@ -882,7 +921,7 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload)
                        lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT;
                }
 
                        lapp_data->flag |= BLO_LIBLINK_USE_PLACEHOLDERS | BLO_LIBLINK_FORCE_INDIRECT;
                }
 
-               lib_relocate_do(bmain, scene, lib, lapp_data, op->reports, do_reload);
+               lib_relocate_do(bmain, lib, lapp_data, op->reports, do_reload);
 
                wm_link_append_data_free(lapp_data);
 
 
                wm_link_append_data_free(lapp_data);