[Bf-blender-cvs] [3be5ce4aad5] master: LibLink: New Append code.

Bastien Montagne noreply at git.blender.org
Tue Sep 14 18:07:32 CEST 2021


Commit: 3be5ce4aad5e4bbc25474511e56036d6980e1cea
Author: Bastien Montagne
Date:   Tue Sep 14 17:49:57 2021 +0200
Branches: master
https://developer.blender.org/rB3be5ce4aad5e4bbc25474511e56036d6980e1cea

LibLink: New Append code.

This commit fully refactors the way linked IDs are made local when
appended.

Previously, `BKE_library_make_local` was (ab)used for this task, but it
was missing some contextual data and doing complex processing to try to
work around this, with limited sucess. Further more, it was nearly
impossibe to extend (e.g. to get new append behaviors necessary for the
asset project).

The new code is a dedicated append step in WM linking process.

NOTE: BPY API (`libray.load()` context manager) uses its own code here,
which still relies on `BKE_library_make_local` for appending.
Unfortunately, merging those two different code paths is not trivial so
for now this API will remain unchanged.

Fix T55629: Append already linked Data is impossible.

===================================================================

M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/windowmanager/intern/wm_files_link.c

===================================================================

diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 2598c53a5e0..bf0463432db 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -3416,7 +3416,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
             case SPACE_FILE: {
               SpaceFile *sfile = (SpaceFile *)sl;
               if (sfile->params) {
-                sfile->params->flag &= ~(FILE_PARAMS_FLAG_UNUSED_1 | FILE_PARAMS_FLAG_UNUSED_6 |
+                sfile->params->flag &= ~(FILE_APPEND_SET_FAKEUSER | FILE_APPEND_RECURSIVE |
                                          FILE_OBDATA_INSTANCE);
               }
               break;
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 863c53615c1..13e6904662e 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -936,13 +936,13 @@ typedef enum eFileSel_Action {
  * (WM and BLO code area, see #eBLOLibLinkFlags in BLO_readfile.h).
  */
 typedef enum eFileSel_Params_Flag {
-  FILE_PARAMS_FLAG_UNUSED_1 = (1 << 0), /* cleared */
+  FILE_APPEND_SET_FAKEUSER = (1 << 0),
   FILE_RELPATH = (1 << 1),
   FILE_LINK = (1 << 2),
   FILE_HIDE_DOT = (1 << 3),
   FILE_AUTOSELECT = (1 << 4),
   FILE_ACTIVE_COLLECTION = (1 << 5),
-  FILE_PARAMS_FLAG_UNUSED_6 = (1 << 6), /* cleared */
+  FILE_APPEND_RECURSIVE = (1 << 6),
   FILE_DIRSEL_ONLY = (1 << 7),
   FILE_FILTER = (1 << 8),
   FILE_OBDATA_INSTANCE = (1 << 9),
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 606c9252ff9..4affabb6da2 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -35,7 +35,9 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_ID.h"
+#include "DNA_collection_types.h"
 #include "DNA_key_types.h"
+#include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_windowmanager_types.h"
@@ -50,15 +52,21 @@
 
 #include "BLO_readfile.h"
 
+#include "BKE_armature.h"
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
 #include "BKE_layer.h"
 #include "BKE_lib_id.h"
 #include "BKE_lib_override.h"
+#include "BKE_lib_query.h"
 #include "BKE_lib_remap.h"
 #include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_object.h"
 #include "BKE_report.h"
+#include "BKE_rigidbody.h"
+#include "BKE_scene.h"
 
 #include "BKE_idtype.h"
 
@@ -137,6 +145,14 @@ static short wm_link_append_flag(wmOperator *op)
   if (RNA_boolean_get(op->ptr, "link")) {
     flag |= FILE_LINK;
   }
+  else {
+    if (RNA_boolean_get(op->ptr, "use_recursive")) {
+      flag |= FILE_APPEND_RECURSIVE;
+    }
+    if (RNA_boolean_get(op->ptr, "set_fake")) {
+      flag |= FILE_APPEND_SET_FAKEUSER;
+    }
+  }
   if (RNA_boolean_get(op->ptr, "instance_collections")) {
     flag |= FILE_COLLECTION_INSTANCE;
   }
@@ -153,6 +169,10 @@ typedef struct WMLinkAppendDataItem {
       *libraries; /* All libs (from WMLinkAppendData.libraries) to try to load this ID from. */
   short idcode;
 
+  /** Type of action to do to append this item, and other append-specific information. */
+  char append_action;
+  char append_tag;
+
   ID *new_id;
   void *customdata;
 } WMLinkAppendDataItem;
@@ -167,10 +187,32 @@ typedef struct WMLinkAppendData {
    */
   int flag;
 
+  /** Allows to easily find an existing items from an ID pointer. Used by append code. */
+  GHash *new_id_to_item;
+
   /* Internal 'private' data */
   MemArena *memarena;
 } WMLinkAppendData;
 
+typedef struct WMLinkAppendDataCallBack {
+  WMLinkAppendData *lapp_data;
+  WMLinkAppendDataItem *item;
+  ReportList *reports;
+
+} WMLinkAppendDataCallBack;
+
+enum {
+  WM_APPEND_ACT_UNSET = 0,
+  WM_APPEND_ACT_KEEP_LINKED,
+  WM_APPEND_ACT_REUSE_LOCAL,
+  WM_APPEND_ACT_MAKE_LOCAL,
+  WM_APPEND_ACT_COPY_LOCAL,
+};
+
+enum {
+  WM_APPEND_TAG_INDIRECT = 1 << 0,
+};
+
 static WMLinkAppendData *wm_link_append_data_new(const int flag)
 {
   MemArena *ma = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
@@ -184,6 +226,10 @@ static WMLinkAppendData *wm_link_append_data_new(const int flag)
 
 static void wm_link_append_data_free(WMLinkAppendData *lapp_data)
 {
+  if (lapp_data->new_id_to_item != NULL) {
+    BLI_ghash_free(lapp_data->new_id_to_item, NULL, NULL);
+  }
+
   BLI_memarena_free(lapp_data->memarena);
 }
 
@@ -213,6 +259,7 @@ static WMLinkAppendDataItem *wm_link_append_data_item_add(WMLinkAppendData *lapp
   item->libraries = BLI_BITMAP_NEW_MEMARENA(lapp_data->memarena, lapp_data->num_libraries);
 
   item->new_id = NULL;
+  item->append_action = WM_APPEND_ACT_UNSET;
   item->customdata = customdata;
 
   BLI_linklist_append_arena(&lapp_data->items, item, lapp_data->memarena);
@@ -221,6 +268,567 @@ static WMLinkAppendDataItem *wm_link_append_data_item_add(WMLinkAppendData *lapp
   return item;
 }
 
+/* -------------------------------------------------------------------- */
+/** \name Library appending helper functions.
+ *
+ *  FIXME: Deduplicate code with similar one in readfile.c
+ * \{ */
+
+static bool object_in_any_scene(Main *bmain, Object *ob)
+{
+  LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
+    if (BKE_scene_object_find(sce, ob)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static bool object_in_any_collection(Main *bmain, Object *ob)
+{
+  LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
+    if (BKE_collection_has_object(collection, ob)) {
+      return true;
+    }
+  }
+
+  LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+    if (scene->master_collection != NULL &&
+        BKE_collection_has_object(scene->master_collection, ob)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/**
+ * Shared operations to perform on the object's base after adding it to the scene.
+ */
+static void wm_append_loose_data_instantiate_object_base_instance_init(
+    Object *ob, bool set_selected, bool set_active, ViewLayer *view_layer, const View3D *v3d)
+{
+  Base *base = BKE_view_layer_base_find(view_layer, ob);
+
+  if (v3d != NULL) {
+    base->local_view_bits |= v3d->local_view_uuid;
+  }
+
+  if (set_selected) {
+    if (base->flag & BASE_SELECTABLE) {
+      base->flag |= BASE_SELECTED;
+    }
+  }
+
+  if (set_active) {
+    view_layer->basact = base;
+  }
+
+  BKE_scene_object_base_flag_sync_from_base(base);
+}
+
+static ID *wm_append_loose_data_instantiate_process_check(WMLinkAppendDataItem *item)
+{
+  /* We consider that if we either kept it linked, or re-used already local data, instantiation
+   * status of those should not be modified. */
+  if (!ELEM(item->append_action, WM_APPEND_ACT_COPY_LOCAL, WM_APPEND_ACT_MAKE_LOCAL)) {
+    return NULL;
+  }
+
+  ID *id = item->new_id;
+  if (id == NULL) {
+    return NULL;
+  }
+
+  if (item->append_action == WM_APPEND_ACT_COPY_LOCAL) {
+    BLI_assert(ID_IS_LINKED(id));
+    id = id->newid;
+    if (id == NULL) {
+      return NULL;
+    }
+
+    BLI_assert(!ID_IS_LINKED(id));
+    return id;
+  }
+
+  BLI_assert(!ID_IS_LINKED(id));
+  return id;
+}
+
+static void wm_append_loose_data_instantiate_ensure_active_collection(
+    WMLinkAppendData *lapp_data,
+    Main *bmain,
+    Scene *scene,
+    ViewLayer *view_layer,
+    Collection **r_active_collection)
+{
+  /* Find or add collection as needed. */
+  if (*r_active_collection == NULL) {
+    if (lapp_data->flag & FILE_ACTIVE_COLLECTION) {
+      LayerCollection *lc = BKE_layer_collection_get_active(view_layer);
+      *r_active_collection = lc->collection;
+    }
+    else {
+      *r_active_collection = BKE_collection_add(bmain, scene->master_collection, NULL);
+    }
+  }
+}
+
+/* TODO: De-duplicate this code with the one in readfile.c, think we need some utils code for that
+ * in BKE. */
+static void wm_append_loose_data_instantiate(WMLinkAppendData *lapp_data,
+                                             Main *bmain,
+                                             Scene *scene,
+                                             ViewLayer *view_layer,
+                                             const View3D *v3d)
+{
+  LinkNode *itemlink;
+  Collection *active_collection = NULL;
+  const bool do_obdata = (lapp_data->flag & FILE_OBDATA_INSTANCE) != 0;
+
+  const bool object_set_selected = (lapp_data->flag & FILE_AUTOSELECT) != 0;
+  /* Do NOT make base active here! screws up GUI stuff,
+   * if you want it do it at the editor level. */
+  const bool object_set_active = false;
+
+  /* First pass on obdata to enable their instantiation by default, then do a second pass on
+   * objects to clear it for any obdata already in use. */
+  if (do_obdata) {
+    for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
+      WMLinkAppendDataItem *item = itemlink->link;
+      ID *id = wm_append_loose_data_instantiate_process_check(item);
+      if (id == NULL) {
+        continue;
+      }
+      const ID_Type idcode = GS(id->name);
+      if (!OB_DATA_SUPPORT_ID(idcode)) {
+        continue;
+      }
+
+      id->tag |= LIB_TAG_DOIT;
+    }
+    for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
+      WMLinkAppendDataItem *item = itemlink->link;
+      ID *id = item->new_id;
+      if (id == NULL || GS(id->name) != ID_OB) {
+        continue;
+      }
+
+      Object *ob = (Object *)id;
+      Object *new_ob = (Object *)id->newid;
+      if (ob->data != NULL) {
+        ((ID *)(ob->data))->tag &= ~LIB_TAG_DOIT;
+      }
+      if (new_ob != NULL && new_ob->data != NULL) {
+        ((ID *)(new_ob->data))->tag &= ~LIB_TAG_DOIT;
+      }
+    }
+  }
+
+  /* First do collections, then objects, then obdata. */
+
+  /* NOTE: For collections we only view_layer-instantiate duplicated collections that have
+   * non-instantiated objects in them. */
+  for (itemlink = lapp_data->items.list; itemlink; itemlink = itemlink->next) {
+    WMLinkAppendDataItem *item = itemlink->link;
+    ID *id = wm_append_loose_data_instantiate_process_check(item);
+    if (id == NULL || GS(id->name) != ID_GR) {
+      contin

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list