Fix T60366: texture paint slots not updating when editing material.

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.
This commit is contained in:
Brecht Van Lommel 2019-02-28 14:09:19 +01:00
parent acd4623471
commit da1323d1c9
Notes: blender-bot 2023-02-14 04:07:54 +01:00
Referenced by commit a261d6f2d3, Fix T62328, T62209: revert recent fix for texture slots updates (T60366).
Referenced by issue #60366, Creating a new image texture in shader editor does not appear among the texture slots
8 changed files with 48 additions and 66 deletions

View 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);

View 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)
if (ma == NULL) {
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);
/* Compute texture paint slots. */
TexPaintSlot *texpaintslot = NULL;
int tot_slots = (ma->nodetree) ? count_texture_nodes_recursive(ma->nodetree) : 0;
if (tot_slots) {
texpaintslot = MEM_callocN(sizeof(*texpaintslot) * tot_slots, "texpaint_slots");
bNode *active_node = nodeGetActiveTexture(ma->nodetree);
int index = 0;
fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, texpaintslot, &index);
}
/* Keep active slots within range. */
if (ma->paint_active_slot >= tot_slots) {
ma->paint_active_slot = MAX2(tot_slots - 1, 0);
}
if (ma->paint_clone_slot >= tot_slots) {
ma->paint_clone_slot = MAX2(tot_slots - 1, 0);
}
/* Replace slots. */
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;
return;
}
if (!(ma->nodetree)) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
return;
}
count = count_texture_nodes_recursive(ma->nodetree);
if (count == 0) {
ma->paint_active_slot = 0;
ma->paint_clone_slot = 0;
return;
}
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;
if (ma->paint_active_slot >= count) {
ma->paint_active_slot = count - 1;
}
if (ma->paint_clone_slot >= count) {
ma->paint_clone_slot = count - 1;
}
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])
{

View 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) {

View 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);
}
}

View 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);

View 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);

View 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);
}
}

View 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);