Fix T60366: texture paint slots not updating when editing material.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 28 Feb 2019 13:09:19 +0000 (14:09 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 28 Feb 2019 18:17:16 +0000 (19:17 +0100)
Now always refresh when the material changes. Depsgraph tag moved out
of the refresh function since that gets called on depsgraph update,
which should not trigger a second depsgraph update.

source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/intern/material.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/render/render_update.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/util/ed_util.c
source/blender/makesrna/intern/rna_sculpt_paint.c

index 1c171ef..84760a5 100644 (file)
@@ -83,8 +83,8 @@ bool  BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob);
 
 struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act);
 
-void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
-void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
+void BKE_texpaint_slot_refresh_cache(struct Material *ma);
+void BKE_texpaint_slots_refresh_object(struct Object *ob);
 
 /* rna api */
 void BKE_material_resize_id(struct Main *bmain, struct ID *id, short totcol, bool do_id_user);
index f6bd5a8..138a642 100644 (file)
@@ -228,6 +228,7 @@ Material *BKE_material_localize(Material *ma)
        Material *man = BKE_libblock_copy_for_localize(&ma->id);
 
        man->texpaintslot = NULL;
+       man->tot_slots = 0;
        man->preview = NULL;
 
        if (ma->nodetree != NULL) {
@@ -1046,7 +1047,7 @@ static int count_texture_nodes_recursive(bNodeTree *nodetree)
        return tex_nodes;
 }
 
-static void fill_texpaint_slots_recursive(bNodeTree *nodetree, bNode *active_node, Material *ma, int *index)
+static void fill_texpaint_slots_recursive(bNodeTree *nodetree, bNode *active_node, Material *ma, TexPaintSlot *slots, int *index)
 {
        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) {
@@ -1054,99 +1055,77 @@ static void fill_texpaint_slots_recursive(bNodeTree *nodetree, bNode *active_nod
                                ma->paint_active_slot = *index;
                        }
 
-                       ma->texpaintslot[*index].ima = (Image *)node->id;
-                       ma->texpaintslot[*index].interp = ((NodeTexImage *)node->storage)->interpolation;
+                       slots[*index].ima = (Image *)node->id;
+                       slots[*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;
+                               slots[*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;
+                               slots[*index].valid = true;
                        }
                        else {
                                /* just invalidate the index here so UV map does not get displayed on the UI */
-                               ma->texpaintslot[*index].valid = false;
+                               slots[*index].valid = false;
                        }
                        (*index)++;
                }
                else if (node->type == NODE_GROUP) {
                        /* recurse into the node group and see if it contains any textures */
-                       fill_texpaint_slots_recursive((bNodeTree *)node->id, active_node, ma, index);
+                       fill_texpaint_slots_recursive((bNodeTree *)node->id, active_node, ma, slots, index);
                }
        }
 }
 
-void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
+void BKE_texpaint_slot_refresh_cache(Material *ma)
 {
-       int count = 0;
-       int index = 0;
-
-       if (!ma)
-               return;
-
-       /* COW needed when adding texture slot on an object with no materials. */
-       DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE);
-
-       if (ma->texpaintslot) {
-               MEM_freeN(ma->texpaintslot);
-               ma->tot_slots = 0;
-               ma->texpaintslot = NULL;
-       }
-
-       if (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_IMAGE) {
-               ma->paint_active_slot = 0;
-               ma->paint_clone_slot = 0;
+       if (ma == NULL) {
                return;
        }
 
-       if (!(ma->nodetree)) {
-               ma->paint_active_slot = 0;
-               ma->paint_clone_slot = 0;
-               return;
-       }
+       /* Compute texture paint slots. */
+       TexPaintSlot *texpaintslot = NULL;
+       int tot_slots = (ma->nodetree) ? count_texture_nodes_recursive(ma->nodetree) : 0;
 
-       count = count_texture_nodes_recursive(ma->nodetree);
+       if (tot_slots) {
+               texpaintslot = MEM_callocN(sizeof(*texpaintslot) * tot_slots, "texpaint_slots");
 
-       if (count == 0) {
-               ma->paint_active_slot = 0;
-               ma->paint_clone_slot = 0;
-               return;
+               bNode *active_node = nodeGetActiveTexture(ma->nodetree);
+               int index = 0;
+               fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, texpaintslot, &index);
        }
 
-       ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots");
-
-       bNode *active_node = nodeGetActiveTexture(ma->nodetree);
-
-       fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, &index);
-
-       ma->tot_slots = count;
-
+       /* Keep active slots within range. */
+       if (ma->paint_active_slot >= tot_slots) {
+               ma->paint_active_slot = MAX2(tot_slots - 1, 0);
+       }
 
-       if (ma->paint_active_slot >= count) {
-               ma->paint_active_slot = count - 1;
+       if (ma->paint_clone_slot >= tot_slots) {
+               ma->paint_clone_slot = MAX2(tot_slots - 1, 0);
        }
 
-       if (ma->paint_clone_slot >= count) {
-               ma->paint_clone_slot = count - 1;
+       /* Replace slots. */
+       if (ma->texpaintslot) {
+               MEM_freeN(ma->texpaintslot);
        }
 
-       return;
+       ma->texpaintslot = texpaintslot;
+       ma->tot_slots = tot_slots;
 }
 
-void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob)
+void BKE_texpaint_slots_refresh_object(struct Object *ob)
 {
        int i;
 
        for (i = 1; i < ob->totcol + 1; i++) {
                Material *ma = give_current_material(ob, i);
-               BKE_texpaint_slot_refresh_cache(scene, ma);
+               BKE_texpaint_slot_refresh_cache(ma);
        }
 }
 
-
 /* 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 250c4aa..7145e67 100644 (file)
@@ -4513,6 +4513,7 @@ static void direct_link_material(FileData *fd, Material *ma)
        direct_link_animdata(fd, ma->adt);
 
        ma->texpaintslot = NULL;
+       ma->tot_slots = 0;
 
        ma->nodetree = newdataadr(fd, ma->nodetree);
        if (ma->nodetree) {
index 462fd99..6e6154e 100644 (file)
@@ -206,6 +206,8 @@ void ED_render_engine_changed(Main *bmain)
 
 static void material_changed(Main *UNUSED(bmain), Material *ma)
 {
+       BKE_texpaint_slot_refresh_cache(ma);
+
        /* icons */
        BKE_icon_changed(BKE_icon_id_ensure(&ma->id));
 }
@@ -266,7 +268,7 @@ static void scene_changed(Main *bmain, Scene *scene)
        /* glsl */
        for (ob = bmain->object.first; ob; ob = ob->id.next) {
                if (ob->mode & OB_MODE_TEXTURE_PAINT) {
-                       BKE_texpaint_slots_refresh_object(scene, ob);
+                       BKE_texpaint_slots_refresh_object(ob);
                        BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
                }
        }
index 44f05c3..9d90b6f 100644 (file)
@@ -1095,7 +1095,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op)
 
                /* This has to stay here to regenerate the texture paint
                 * cache in case we are loading a file */
-               BKE_texpaint_slots_refresh_object(scene, ob);
+               BKE_texpaint_slots_refresh_object(ob);
 
                BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
 
index d803b4d..b4abab0 100644 (file)
@@ -5757,7 +5757,7 @@ bool BKE_paint_proj_mesh_data_check(Scene *scene, Object *ob, bool *uvs, bool *m
                                        hasmat = true;
                                        if (!ma->texpaintslot) {
                                                /* refresh here just in case */
-                                               BKE_texpaint_slot_refresh_cache(scene, ma);
+                                               BKE_texpaint_slot_refresh_cache(ma);
 
                                                /* if still no slots, we have to add */
                                                if (ma->texpaintslot) {
@@ -6017,13 +6017,13 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
                nodePositionPropagate(out_node);
 
                if (ima) {
-                       BKE_texpaint_slot_refresh_cache(scene, ma);
+                       BKE_texpaint_slot_refresh_cache(ma);
                        BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
                        WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
                }
 
                DEG_id_tag_update(&ntree->id, 0);
-               DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
+               DEG_id_tag_update(&ma->id, ID_RECALC_SHADING | ID_RECALC_COPY_ON_WRITE);
                ED_area_tag_redraw(CTX_wm_area(C));
 
                BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
index 6f0c859..ea99dd9 100644 (file)
@@ -90,7 +90,7 @@ void ED_editors_init_for_undo(Main *bmain)
                        if (ob->mode & OB_MODE_TEXTURE_PAINT) {
                                Scene *scene = WM_window_get_active_scene(win);
 
-                               BKE_texpaint_slots_refresh_object(scene, ob);
+                               BKE_texpaint_slots_refresh_object(ob);
                                BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);
                        }
                }
index ed51129..c872200 100644 (file)
@@ -455,7 +455,7 @@ static void rna_ImaPaint_mode_update(bContext *C, PointerRNA *UNUSED(ptr))
 
        if (ob && ob->type == OB_MESH) {
                /* of course we need to invalidate here */
-               BKE_texpaint_slots_refresh_object(scene, ob);
+               BKE_texpaint_slots_refresh_object(ob);
 
                /* we assume that changing the current mode will invalidate the uv layers so we need to refresh display */
                BKE_paint_proj_mesh_data_check(scene, ob, NULL, NULL, NULL, NULL);