[Bf-blender-cvs] [33c5e7bcd5e] blender-v3.0-release: LibOverrides: Refactor how diffing of RNA collections is handled.

Bastien Montagne noreply at git.blender.org
Fri Nov 19 15:42:21 CET 2021


Commit: 33c5e7bcd5e5b790ee95caaa0c4d917996341266
Author: Bastien Montagne
Date:   Fri Nov 19 09:33:52 2021 +0100
Branches: blender-v3.0-release
https://developer.blender.org/rB33c5e7bcd5e5b790ee95caaa0c4d917996341266

LibOverrides: Refactor how diffing of RNA collections is handled.

Original implementation was a quick prototype which should have never
landed as-is in master. It had very limiting constraints and did not
allow for any real further development.

This commit fixes the internal implementation to make more sensible,
maintainable and evolutive.

NOTE: This commit introduces another forward-incompatibility in the
Blender file format: Files saved after this commit won't open properly
in older versions of blender regarding local inserted constraints or
modifiers into overrides of linked data.

NOTE: Technical details: The 'anchor' item name/index is now stored in
`subitem_reference_` members, and the actual 'source' item name/index is
stored in `subitem_local_` members of the override property operation
data.
Previously, only the `subitem_local_` members were used, storing the
anchor item name/index, and assuming the 'source' item was always the
next in the list.

Milestone I of T82160.

Maniphest Tasks: T82160

Differential Revision: https://developer.blender.org/D13282

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

M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/makesdna/DNA_ID.h
M	source/blender/makesrna/intern/rna_animation.c
M	source/blender/makesrna/intern/rna_object.c
M	source/blender/makesrna/intern/rna_pose.c
M	source/blender/makesrna/intern/rna_rna.c

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

diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 6bdec0d70f3..326ca746292 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,13 +39,13 @@ extern "C" {
 
 /* Blender file format version. */
 #define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 41
+#define BLENDER_FILE_SUBVERSION 42
 
 /* Minimum Blender version that supports reading file written with the current
  * version. Older Blender versions will test this and show a warning if the file
  * was written with too new a version. */
 #define BLENDER_FILE_MIN_VERSION 300
-#define BLENDER_FILE_MIN_SUBVERSION 36
+#define BLENDER_FILE_MIN_SUBVERSION 42
 
 /** User readable version string. */
 const char *BKE_blender_version_string(void);
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index 98264883507..18baebf57fb 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -22,6 +22,8 @@
 
 #include <string.h>
 
+#include "CLG_log.h"
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_listbase.h"
@@ -46,6 +48,7 @@
 #include "DNA_workspace_types.h"
 
 #include "BKE_action.h"
+#include "BKE_anim_data.h"
 #include "BKE_animsys.h"
 #include "BKE_armature.h"
 #include "BKE_asset.h"
@@ -55,6 +58,7 @@
 #include "BKE_fcurve_driver.h"
 #include "BKE_idprop.h"
 #include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
 #include "BKE_main.h"
 #include "BKE_modifier.h"
 #include "BKE_node.h"
@@ -74,6 +78,8 @@
 
 #include "versioning_common.h"
 
+static CLG_LogRef LOG = {"blo.readfile.doversion"};
+
 static IDProperty *idproperty_find_ui_container(IDProperty *idprop_group)
 {
   LISTBASE_FOREACH (IDProperty *, prop, &idprop_group->data.group) {
@@ -1282,6 +1288,140 @@ static bool version_fix_seq_meta_range(Sequence *seq, void *user_data)
   return true;
 }
 
+/* Those `version_liboverride_rnacollections_*` functions mimic the old, pre-3.0 code to find
+ * anchor and source items in the given list of modifiers, constraints etc., using only the
+ * `subitem_local` data of the override property operation.
+ *
+ * Then they convert it into the new, proper `subitem_reference` data for the anchor, and
+ * `subitem_local` for the source.
+ *
+ * NOTE: Here only the stored override ID is available, unlike in the `override_apply` functions.
+ */
+
+static void version_liboverride_rnacollections_insertion_object_constraints(
+    ListBase *constraints, IDOverrideLibraryProperty *op)
+{
+  LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
+    if (opop->operation != IDOVERRIDE_LIBRARY_OP_INSERT_AFTER) {
+      continue;
+    }
+    bConstraint *constraint_anchor = BLI_listbase_string_or_index_find(constraints,
+                                                                       opop->subitem_local_name,
+                                                                       offsetof(bConstraint, name),
+                                                                       opop->subitem_local_index);
+    if (constraint_anchor == NULL || constraint_anchor->next == NULL) {
+      /* Invalid case, just remove that override property operation. */
+      CLOG_ERROR(&LOG, "Could not find anchor or source constraints in stored override data");
+      BKE_lib_override_library_property_operation_delete(op, opop);
+      continue;
+    }
+    bConstraint *constraint_src = constraint_anchor->next;
+    opop->subitem_reference_name = opop->subitem_local_name;
+    opop->subitem_local_name = BLI_strdup(constraint_src->name);
+    opop->subitem_reference_index = opop->subitem_local_index;
+    opop->subitem_local_index++;
+  }
+}
+
+static void version_liboverride_rnacollections_insertion_object(Object *object)
+{
+  IDOverrideLibrary *liboverride = object->id.override_library;
+  IDOverrideLibraryProperty *op;
+
+  op = BKE_lib_override_library_property_find(liboverride, "modifiers");
+  if (op != NULL) {
+    LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
+      if (opop->operation != IDOVERRIDE_LIBRARY_OP_INSERT_AFTER) {
+        continue;
+      }
+      ModifierData *mod_anchor = BLI_listbase_string_or_index_find(&object->modifiers,
+                                                                   opop->subitem_local_name,
+                                                                   offsetof(ModifierData, name),
+                                                                   opop->subitem_local_index);
+      if (mod_anchor == NULL || mod_anchor->next == NULL) {
+        /* Invalid case, just remove that override property operation. */
+        CLOG_ERROR(&LOG, "Could not find anchor or source modifiers in stored override data");
+        BKE_lib_override_library_property_operation_delete(op, opop);
+        continue;
+      }
+      ModifierData *mod_src = mod_anchor->next;
+      opop->subitem_reference_name = opop->subitem_local_name;
+      opop->subitem_local_name = BLI_strdup(mod_src->name);
+      opop->subitem_reference_index = opop->subitem_local_index;
+      opop->subitem_local_index++;
+    }
+  }
+
+  op = BKE_lib_override_library_property_find(liboverride, "grease_pencil_modifiers");
+  if (op != NULL) {
+    LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
+      if (opop->operation != IDOVERRIDE_LIBRARY_OP_INSERT_AFTER) {
+        continue;
+      }
+      GpencilModifierData *gp_mod_anchor = BLI_listbase_string_or_index_find(
+          &object->greasepencil_modifiers,
+          opop->subitem_local_name,
+          offsetof(GpencilModifierData, name),
+          opop->subitem_local_index);
+      if (gp_mod_anchor == NULL || gp_mod_anchor->next == NULL) {
+        /* Invalid case, just remove that override property operation. */
+        CLOG_ERROR(&LOG, "Could not find anchor GP modifier in stored override data");
+        BKE_lib_override_library_property_operation_delete(op, opop);
+        continue;
+      }
+      GpencilModifierData *gp_mod_src = gp_mod_anchor->next;
+      opop->subitem_reference_name = opop->subitem_local_name;
+      opop->subitem_local_name = BLI_strdup(gp_mod_src->name);
+      opop->subitem_reference_index = opop->subitem_local_index;
+      opop->subitem_local_index++;
+    }
+  }
+
+  op = BKE_lib_override_library_property_find(liboverride, "constraints");
+  if (op != NULL) {
+    version_liboverride_rnacollections_insertion_object_constraints(&object->constraints, op);
+  }
+
+  if (object->pose != NULL) {
+    LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+      char rna_path[FILE_MAXFILE];
+      BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].constraints", pchan->name);
+      op = BKE_lib_override_library_property_find(liboverride, rna_path);
+      if (op != NULL) {
+        version_liboverride_rnacollections_insertion_object_constraints(&pchan->constraints, op);
+      }
+    }
+  }
+}
+
+static void version_liboverride_rnacollections_insertion_animdata(ID *id)
+{
+  AnimData *anim_data = BKE_animdata_from_id(id);
+  if (anim_data == NULL) {
+    return;
+  }
+
+  IDOverrideLibrary *liboverride = id->override_library;
+  IDOverrideLibraryProperty *op;
+
+  op = BKE_lib_override_library_property_find(liboverride, "animation_data.nla_tracks");
+  if (op != NULL) {
+    LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
+      if (opop->operation != IDOVERRIDE_LIBRARY_OP_INSERT_AFTER) {
+        continue;
+      }
+      /* NLA tracks are only referenced by index, which limits possibilities, basically they are
+       * always added at the end of the list, see #rna_NLA_tracks_override_apply.
+       *
+       * This makes things simple here. */
+      opop->subitem_reference_name = opop->subitem_local_name;
+      opop->subitem_local_name = NULL;
+      opop->subitem_reference_index = opop->subitem_local_index;
+      opop->subitem_local_index++;
+    }
+  }
+}
+
 /* NOLINTNEXTLINE: readability-function-size */
 void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
 {
@@ -2158,16 +2298,20 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
     }
   }
 
-  /**
-   * Versioning code until next subversion bump goes here.
-   *
-   * \note Be sure to check when bumping the version:
-   * - "versioning_userdef.c", #blo_do_versions_userdef
-   * - "versioning_userdef.c", #do_versions_theme
-   *
-   * \note Keep this message at the bottom of the function.
-   */
-  {
+  if (!MAIN_VERSION_ATLEAST(bmain, 300, 42)) {
+    /* Update LibOverride operations regarding insertions in RNA collections (i.e. modifiers,
+     * constraints and NLA tracks). */
+    ID *id_iter;
+    FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+      if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) {
+        version_liboverride_rnacollections_insertion_animdata(id_iter);
+        if (GS(id_iter->name) == ID_OB) {
+          version_liboverride_rnacollections_insertion_object((Object *)id_iter);
+        }
+      }
+    }
+    FOREACH_MAIN_ID_END;
+
     /* Use consistent socket identifiers for the math node.
      * The code to make unique identifiers from the names was inconsistent. */
     FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
@@ -2215,4 +2359,16 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
       }
     }
   }
+
+  /**
+   * Versioning code until next subversion bump goes here.
+   *
+   * \note Be sure to check when bumping the version:
+   * - "versioning_userdef.c", #blo_do_versions_userdef
+   * - "versioning_userdef.c", #do_versions_theme
+   *
+   * \note Keep this message at the bottom of the function.
+   */
+  {
+  }
 }
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index d829d707a71..2c04d0b06ef 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -211,11 +211,15 @@ typedef struct IDOverrideLibraryPropertyOperation {
   char _pad0[2];
 
   /* Sub-item references, if needed (for

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list