Fix T67597: Texture painting: Texture slots that correspond to nodes inside node_grou...
authormano-wii <germano.costa@ig.com.br>
Wed, 31 Jul 2019 14:37:03 +0000 (11:37 -0300)
committermano-wii <germano.costa@ig.com.br>
Wed, 31 Jul 2019 14:39:30 +0000 (11:39 -0300)
Unlike `fill_texpaint_slots_recursive`, `rna_Material_active_paint_texture_index_update` did not search for texture nodes that are inside node groups.

Reviewers: sergey, psy-fi, zeddb, brecht

Subscribers: brecht

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

source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/intern/material.c
source/blender/makesrna/intern/rna_material.c

index 9d8b9218a792717921e90c423cd2b8dc90c04953..268cf831456f96d40f84ee8d585d1bf124f42276 100644 (file)
@@ -28,6 +28,7 @@
 extern "C" {
 #endif
 
+struct bNode;
 struct ID;
 struct Main;
 struct Material;
@@ -94,6 +95,7 @@ struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob
 
 void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
 void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
+struct bNode *BKE_texpaint_slot_material_find_node(struct Material *ma, short texpaint_slot);
 
 /* rna api */
 void BKE_material_resize_id(struct Main *bmain, struct ID *id, short totcol, bool do_id_user);
index e845271d802ad6802cd3de098580ebe1da36e1f4..6fdc1995ca572e5358d099a442763abe64e5cd23 100644 (file)
@@ -1085,65 +1085,93 @@ static bNode *nodetree_uv_node_recursive(bNode *node)
   return NULL;
 }
 
-static int count_texture_nodes_recursive(bNodeTree *nodetree)
+typedef bool (*ForEachTexNodeCallback)(bNode *node, void *userdata);
+static bool ntree_foreach_texnode_recursive(bNodeTree *nodetree,
+                                            ForEachTexNodeCallback callback,
+                                            void *userdata)
 {
-  int tex_nodes = 0;
-
   for (bNode *node = nodetree->nodes.first; node; node = node->next) {
     if (node->typeinfo->nclass == NODE_CLASS_TEXTURE &&
         node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
-      tex_nodes++;
+      if (!callback(node, userdata)) {
+        return false;
+      }
     }
     else if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
       /* recurse into the node group and see if it contains any textures */
-      tex_nodes += count_texture_nodes_recursive((bNodeTree *)node->id);
+      if (!ntree_foreach_texnode_recursive((bNodeTree *)node->id, callback, userdata)) {
+        return false;
+      }
     }
   }
+  return true;
+}
+
+static bool count_texture_nodes_cb(bNode *node, void *userdata)
+{
+  (*((int *)userdata))++;
+  return true;
+}
+
+static int count_texture_nodes_recursive(bNodeTree *nodetree)
+{
+  int tex_nodes = 0;
+  ntree_foreach_texnode_recursive(nodetree, count_texture_nodes_cb, &tex_nodes);
 
   return tex_nodes;
 }
 
-static void fill_texpaint_slots_recursive(bNodeTree *nodetree,
-                                          bNode *active_node,
-                                          Material *ma,
-                                          int *index)
+struct FillTexPaintSlotsData {
+  bNode *active_node;
+  Material *ma;
+  int index;
+  int slot_len;
+};
+
+static bool fill_texpaint_slots_cb(bNode *node, void *userdata)
 {
-  for (bNode *node = nodetree->nodes.first; node; node = node->next) {
-    if (node->typeinfo->nclass == NODE_CLASS_TEXTURE &&
-        node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
-      if (active_node == node) {
-        ma->paint_active_slot = *index;
-      }
+  struct FillTexPaintSlotsData *fill_data = userdata;
 
-      ma->texpaintslot[*index].ima = (Image *)node->id;
-      ma->texpaintslot[*index].interp = ((NodeTexImage *)node->storage)->interpolation;
+  Material *ma = fill_data->ma;
+  int index = fill_data->index;
+  fill_data->index++;
 
-      /* for new renderer, we need to traverse the treeback in search of a UV node */
-      bNode *uvnode = nodetree_uv_node_recursive(node);
+  if (fill_data->active_node == node) {
+    ma->paint_active_slot = index;
+  }
 
-      if (uvnode) {
-        NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage;
-        ma->texpaintslot[*index].uvname = storage->uv_map;
-        /* set a value to index so UI knows that we have a valid pointer for the mesh */
-        ma->texpaintslot[*index].valid = true;
-      }
-      else {
-        /* just invalidate the index here so UV map does not get displayed on the UI */
-        ma->texpaintslot[*index].valid = false;
-      }
-      (*index)++;
-    }
-    else if (ELEM(node->type, NODE_GROUP, NODE_CUSTOM_GROUP) && node->id) {
-      /* recurse into the node group and see if it contains any textures */
-      fill_texpaint_slots_recursive((bNodeTree *)node->id, active_node, ma, index);
-    }
+  ma->texpaintslot[index].ima = (Image *)node->id;
+  ma->texpaintslot[index].interp = ((NodeTexImage *)node->storage)->interpolation;
+
+  /* for new renderer, we need to traverse the treeback in search of a UV node */
+  bNode *uvnode = nodetree_uv_node_recursive(node);
+
+  if (uvnode) {
+    NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage;
+    ma->texpaintslot[index].uvname = storage->uv_map;
+    /* set a value to index so UI knows that we have a valid pointer for the mesh */
+    ma->texpaintslot[index].valid = true;
+  }
+  else {
+    /* just invalidate the index here so UV map does not get displayed on the UI */
+    ma->texpaintslot[index].valid = false;
   }
+
+  return fill_data->index != fill_data->slot_len;
+}
+
+static void fill_texpaint_slots_recursive(bNodeTree *nodetree,
+                                          bNode *active_node,
+                                          Material *ma,
+                                          int slot_len)
+{
+  struct FillTexPaintSlotsData fill_data = {active_node, ma, 0, slot_len};
+  ntree_foreach_texnode_recursive(nodetree, fill_texpaint_slots_cb, &fill_data);
 }
 
 void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
 {
   int count = 0;
-  int index = 0;
 
   if (!ma) {
     return;
@@ -1182,7 +1210,7 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
 
   bNode *active_node = nodeGetActiveTexture(ma->nodetree);
 
-  fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, &index);
+  fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, count);
 
   ma->tot_slots = count;
 
@@ -1207,6 +1235,31 @@ void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob)
   }
 }
 
+struct FindTexPaintNodeData {
+  bNode *node;
+  short iter_index;
+  short index;
+};
+
+static bool texpaint_slot_node_find_cb(bNode *node, void *userdata)
+{
+  struct FindTexPaintNodeData *find_data = userdata;
+  if (find_data->iter_index++ == find_data->index) {
+    find_data->node = node;
+    return false;
+  }
+
+  return true;
+}
+
+bNode *BKE_texpaint_slot_material_find_node(Material *ma, short texpaint_slot)
+{
+  struct FindTexPaintNodeData find_data = {NULL, 0, texpaint_slot};
+  ntree_foreach_texnode_recursive(ma->nodetree, texpaint_slot_node_find_cb, &find_data);
+
+  return find_data.node;
+}
+
 /* r_col = current value, col = new value, (fac == 0) is no change */
 void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
 {
index 28989d1dd5f45670f54fe9f961b993e8a77dfad6..162ba6be834e868ac0cb982ef1bce69954c60cc6 100644 (file)
@@ -147,16 +147,8 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain,
   Material *ma = ptr->id.data;
 
   if (ma->use_nodes && ma->nodetree) {
-    struct bNode *node;
-    int index = 0;
-    for (node = ma->nodetree->nodes.first; node; node = node->next) {
-      if (node->typeinfo->nclass == NODE_CLASS_TEXTURE &&
-          node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) {
-        if (index++ == ma->paint_active_slot) {
-          break;
-        }
-      }
-    }
+    struct bNode *node = BKE_texpaint_slot_material_find_node(ma, ma->paint_active_slot);
+
     if (node) {
       nodeSetActive(ma->nodetree, node);
     }