[Bf-blender-cvs] [8f578150eaf] master: Fix T68971: Copy As New Driver from Material node creates a bad reference.

Alexander Gavrilov noreply at git.blender.org
Thu Aug 22 14:52:47 CEST 2019


Commit: 8f578150eaf494a03bed7389046e44f2bdf7d748
Author: Alexander Gavrilov
Date:   Thu Aug 22 15:40:10 2019 +0300
Branches: master
https://developer.blender.org/rB8f578150eaf494a03bed7389046e44f2bdf7d748

Fix T68971: Copy As New Driver from Material node creates a bad reference.

NodeTree structures of materials and some other data blocks are
effectively node group data block objects that are contained inside
the parent block. Thus, direct references to them are only valid
while blender is running, and are lost on save.

Fix Copy As New Driver to create a reference that goes through
the owner data block, by adding a new runtime field to bNodeTree.

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

M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/linestyle.c
M	source/blender/blenkernel/intern/node.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/editors/animation/drivers.c
M	source/blender/editors/include/ED_keyframing.h
M	source/blender/editors/interface/interface_ops.c
M	source/blender/editors/space_node/node_add.c
M	source/blender/editors/space_node/node_edit.c
M	source/blender/editors/space_node/node_group.c
M	source/blender/makesdna/DNA_node_types.h

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

diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index e3d0588b607..b76e3777557 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -366,7 +366,7 @@ struct GHashIterator *ntreeTypeGetIterator(void);
 void ntreeSetTypes(const struct bContext *C, struct bNodeTree *ntree);
 
 void ntreeInitDefault(struct bNodeTree *ntree);
-struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname);
+struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char *idname, struct ID *owner);
 
 /* copy/free funcs, need to manage ID users */
 void ntreeFreeTree(struct bNodeTree *ntree);
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 7bfe5a7c8ff..cdef24b07fb 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -1456,7 +1456,7 @@ void BKE_linestyle_default_shader(const bContext *C, FreestyleLineStyle *linesty
 
   BLI_assert(linestyle->nodetree == NULL);
 
-  ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree");
+  ntree = ntreeAddTree(NULL, "stroke_shader", "ShaderNodeTree", &linestyle->id);
 
   linestyle->nodetree = ntree;
 
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 206c59c110a..59ffbbfea6f 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1394,7 +1394,7 @@ void ntreeInitDefault(bNodeTree *ntree)
   ntree_set_typeinfo(ntree, NULL);
 }
 
-bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
+bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname, ID *owner)
 {
   bNodeTree *ntree;
 
@@ -1408,6 +1408,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
     ntree = MEM_callocN(sizeof(bNodeTree), "new node tree");
     *((short *)ntree->id.name) = ID_NT;
     BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name));
+    ntree->owner = owner;
   }
 
   /* Types are fully initialized at this point,
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1e3342cef04..47fa8704df9 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -3477,13 +3477,15 @@ static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
 }
 
 /* ntree itself has been read! */
-static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
+static void direct_link_nodetree(FileData *fd, bNodeTree *ntree, ID *owner)
 {
   /* note: writing and reading goes in sync, for speed */
   bNode *node;
   bNodeSocket *sock;
   bNodeLink *link;
 
+  ntree->owner = owner;
+
   ntree->init = 0; /* to set callbacks and force setting types */
   ntree->is_updating = false;
   ntree->typeinfo = NULL;
@@ -3958,7 +3960,7 @@ static void direct_link_light(FileData *fd, Light *la)
   la->nodetree = newdataadr(fd, la->nodetree);
   if (la->nodetree) {
     direct_link_id(fd, &la->nodetree->id);
-    direct_link_nodetree(fd, la->nodetree);
+    direct_link_nodetree(fd, la->nodetree, &la->id);
   }
 
   la->preview = direct_link_preview_image(fd, la->preview);
@@ -4121,7 +4123,7 @@ static void direct_link_world(FileData *fd, World *wrld)
   wrld->nodetree = newdataadr(fd, wrld->nodetree);
   if (wrld->nodetree) {
     direct_link_id(fd, &wrld->nodetree->id);
-    direct_link_nodetree(fd, wrld->nodetree);
+    direct_link_nodetree(fd, wrld->nodetree, &wrld->id);
   }
 
   wrld->preview = direct_link_preview_image(fd, wrld->preview);
@@ -4421,7 +4423,7 @@ static void direct_link_texture(FileData *fd, Tex *tex)
   tex->nodetree = newdataadr(fd, tex->nodetree);
   if (tex->nodetree) {
     direct_link_id(fd, &tex->nodetree->id);
-    direct_link_nodetree(fd, tex->nodetree);
+    direct_link_nodetree(fd, tex->nodetree, &tex->id);
   }
 
   tex->preview = direct_link_preview_image(fd, tex->preview);
@@ -4476,7 +4478,7 @@ static void direct_link_material(FileData *fd, Material *ma)
   ma->nodetree = newdataadr(fd, ma->nodetree);
   if (ma->nodetree) {
     direct_link_id(fd, &ma->nodetree->id);
-    direct_link_nodetree(fd, ma->nodetree);
+    direct_link_nodetree(fd, ma->nodetree, &ma->id);
   }
 
   ma->preview = direct_link_preview_image(fd, ma->preview);
@@ -6907,7 +6909,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
   sce->nodetree = newdataadr(fd, sce->nodetree);
   if (sce->nodetree) {
     direct_link_id(fd, &sce->nodetree->id);
-    direct_link_nodetree(fd, sce->nodetree);
+    direct_link_nodetree(fd, sce->nodetree, &sce->id);
   }
 
   direct_link_view_settings(fd, &sce->view_settings);
@@ -8931,7 +8933,7 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle)
   linestyle->nodetree = newdataadr(fd, linestyle->nodetree);
   if (linestyle->nodetree) {
     direct_link_id(fd, &linestyle->nodetree->id);
-    direct_link_nodetree(fd, linestyle->nodetree);
+    direct_link_nodetree(fd, linestyle->nodetree, &linestyle->id);
   }
 }
 
@@ -9293,7 +9295,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const int ta
       direct_link_action(fd, (bAction *)id);
       break;
     case ID_NT:
-      direct_link_nodetree(fd, (bNodeTree *)id);
+      direct_link_nodetree(fd, (bNodeTree *)id, NULL);
       break;
     case ID_BR:
       direct_link_brush(fd, (Brush *)id);
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index e341a16378c..bf2056a7ec6 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -846,6 +846,36 @@ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
 
 /* -------------------------------------------------- */
 
+/** Compute an ID pointer and path to property valid for use in a driver.
+ *  Corrects for ID references that are not independent (e.g. material NodeTree). */
+bool ANIM_get_target_ID_and_path_to_property(
+    PointerRNA *ptr, PropertyRNA *prop, int index, ID **r_id, char **r_path)
+{
+  int dim = RNA_property_array_dimension(ptr, prop, NULL);
+  char *path = RNA_path_from_ID_to_property_index(ptr, prop, dim, index);
+  ID *id = ptr->id.data;
+
+  if (!path) {
+    return false;
+  }
+
+  if (GS(id->name) == ID_NT) {
+    bNodeTree *node_tree = (bNodeTree *)id;
+
+    if (node_tree->owner) {
+      id = node_tree->owner;
+
+      char *new_path = BLI_sprintfN("node_tree%s%s", path[0] == '[' ? "" : ".", path);
+      MEM_freeN(path);
+      path = new_path;
+    }
+  }
+
+  *r_id = id;
+  *r_path = path;
+  return true;
+}
+
 /* Create a driver & variable that reads the specified property,
  * and store it in the buffers for Paste Driver and Paste Variables. */
 void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const char *var_name)
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index bbeeeade822..455337b9cc0 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -403,6 +403,11 @@ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool
 
 /* -------- */
 
+/** Compute an ID pointer and path to property valid for use in a driver.
+ *  Corrects for ID references that are not independent (e.g. material NodeTree). */
+bool ANIM_get_target_ID_and_path_to_property(
+    struct PointerRNA *ptr, struct PropertyRNA *prop, int index, struct ID **r_id, char **r_path);
+
 /* Create a driver & variable that reads the specified property,
  * and store it in the buffers for Paste Driver and Paste Variables. */
 void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const char *var_name);
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index c7ce66cfcf6..f8df8966297 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -195,11 +195,11 @@ static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op))
   UI_context_active_but_prop_get(C, &ptr, &prop, &index);
 
   if (ptr.id.data && ptr.data && prop) {
-    int dim = RNA_property_array_dimension(&ptr, prop, NULL);
-    char *path = RNA_path_from_ID_to_property_index(&ptr, prop, dim, index);
+    ID *id;
+    char *path;
 
-    if (path) {
-      ANIM_copy_as_driver(ptr.id.data, path, RNA_property_identifier(prop));
+    if (ANIM_get_target_ID_and_path_to_property(&ptr, prop, index, &id, &path)) {
+      ANIM_copy_as_driver(id, path, RNA_property_identifier(prop));
       MEM_freeN(path);
       return OPERATOR_FINISHED;
     }
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index 01a30f677a3..5ee1925fd55 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -509,7 +509,7 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
     return OPERATOR_CANCELLED;
   }
 
-  ntree = ntreeAddTree(bmain, treename, idname);
+  ntree = ntreeAddTree(bmain, treename, idname, NULL);
 
   /* hook into UI */
   UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index d31256a1425..46dfa65e73c 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -448,7 +448,7 @@ void ED_node_shader_default(const bContext *C, ID *id)
   int output_type, shader_type;
   float color[4] = {0.0f, 0.0f, 0.0f, 1.0f}, strength = 1.0f;
 
-  ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+  ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname, id);
 
   switch (GS(id->name)) {
     case ID_MA: {
@@ -534,7 +534,7 @@ void ED_node_composit_default(const bContext *C, struct Scene *sce)
     return;
   }
 
-  sce->nodetree = ntreeAddTree(NULL, "Compositing Nodetree", ntreeType_Composite->idname);
+  sce->nodetree 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list