diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_attribute.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_material.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_node.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/attribute.c | 15 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/material.c | 135 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/node.cc | 20 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/paint.c | 7 |
8 files changed, 153 insertions, 45 deletions
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index c5aca6a9373..62469a28eb1 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -122,6 +122,7 @@ struct CustomDataLayer *BKE_id_attributes_active_color_get(const struct ID *id); void BKE_id_attributes_active_color_set(struct ID *id, struct CustomDataLayer *active_layer); struct CustomDataLayer *BKE_id_attributes_render_color_get(const struct ID *id); void BKE_id_attributes_render_color_set(struct ID *id, struct CustomDataLayer *active_layer); +struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const char *name); bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 0870a099c76..f38f6afff7e 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -104,7 +104,9 @@ bool BKE_object_material_slot_used(struct Object *object, short actcol); struct Material *BKE_gpencil_material(struct Object *ob, short act); struct MaterialGPencilStyle *BKE_gpencil_material_settings(struct Object *ob, short act); -void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); +void BKE_texpaint_slot_refresh_cache(struct Scene *scene, + struct Material *ma, + const struct Object *ob); 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); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index fa199300780..23f14f9be9d 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -770,6 +770,14 @@ void nodeClearActive(struct bNodeTree *ntree); * Two active flags, ID nodes have special flag for buttons display. */ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); +struct bNode *nodeGetActivePaintCanvas(struct bNodeTree *ntree); + +/** + * @brief Does the given node supports the sub active flag. + * + * @param sub_active The active flag to check. NODE_ACTIVE_TEXTURE/NODE_ACTIVE_PAINT_CANVAS + */ +bool nodeSupportsActiveFlag(const struct bNode *node, int sub_active); int nodeSocketIsHidden(const struct bNodeSocket *sock); void nodeSetSocketAvailability(struct bNodeTree *ntree, diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 5633c476dc1..1b296277b8f 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -641,6 +641,14 @@ typedef struct SculptSession { */ char needs_flush_to_id; + /** + * Some tools follows the shading chosen by the last used tool canvas. + * When not set the viewport shading color would be used. + * + * NOTE: This setting is temporarily until paint mode is added. + */ + bool sticky_shading_color; + } SculptSession; void BKE_sculptsession_free(struct Object *ob); diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c index c3d4eb72c0d..d8c7c3c6dd7 100644 --- a/source/blender/blenkernel/intern/attribute.c +++ b/source/blender/blenkernel/intern/attribute.c @@ -617,6 +617,21 @@ void BKE_id_attributes_render_color_set(ID *id, CustomDataLayer *active_layer) id, active_layer, CD_FLAG_COLOR_RENDER, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); } +CustomDataLayer *BKE_id_attributes_color_find(const ID *id, const char *name) +{ + CustomDataLayer *layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_POINT); + if (layer == NULL) { + layer = BKE_id_attribute_find(id, name, CD_PROP_COLOR, ATTR_DOMAIN_CORNER); + } + if (layer == NULL) { + layer = BKE_id_attribute_find(id, name, CD_MLOOPCOL, ATTR_DOMAIN_POINT); + } + if (layer == NULL) { + layer = BKE_id_attribute_find(id, name, CD_MLOOPCOL, ATTR_DOMAIN_CORNER); + } + return layer; +} + void BKE_id_attribute_copy_domains_temp(short id_type, const CustomData *vdata, const CustomData *edata, diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 7d01a92e829..bc569956f66 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -43,6 +43,7 @@ #include "BLT_translation.h" #include "BKE_anim_data.h" +#include "BKE_attribute.h" #include "BKE_brush.h" #include "BKE_curve.h" #include "BKE_displist.h" @@ -1347,21 +1348,36 @@ static bNode *nodetree_uv_node_recursive(bNode *node) return NULL; } +/** Bitwise filter for updating paint slots. */ +typedef enum ePaintSlotFilter { + PAINT_SLOT_IMAGE = 1 << 0, + PAINT_SLOT_COLOR_ATTRIBUTE = 1 << 1, +} ePaintSlotFilter; + typedef bool (*ForEachTexNodeCallback)(bNode *node, void *userdata); static bool ntree_foreach_texnode_recursive(bNodeTree *nodetree, ForEachTexNodeCallback callback, - void *userdata) + void *userdata, + ePaintSlotFilter slot_filter) { + const bool do_image_nodes = (slot_filter & PAINT_SLOT_IMAGE) != 0; + const bool do_color_attributes = (slot_filter & PAINT_SLOT_COLOR_ATTRIBUTE) != 0; LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) { - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && + if (do_image_nodes && node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) { if (!callback(node, userdata)) { return false; } } + if (do_color_attributes && node->typeinfo->type == SH_NODE_ATTRIBUTE) { + 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 */ - if (!ntree_foreach_texnode_recursive((bNodeTree *)node->id, callback, userdata)) { + if (!ntree_foreach_texnode_recursive( + (bNodeTree *)node->id, callback, userdata, slot_filter)) { return false; } } @@ -1375,16 +1391,17 @@ static bool count_texture_nodes_cb(bNode *UNUSED(node), void *userdata) return true; } -static int count_texture_nodes_recursive(bNodeTree *nodetree) +static int count_texture_nodes_recursive(bNodeTree *nodetree, ePaintSlotFilter slot_filter) { int tex_nodes = 0; - ntree_foreach_texnode_recursive(nodetree, count_texture_nodes_cb, &tex_nodes); + ntree_foreach_texnode_recursive(nodetree, count_texture_nodes_cb, &tex_nodes, slot_filter); return tex_nodes; } struct FillTexPaintSlotsData { bNode *active_node; + const Object *ob; Material *ma; int index; int slot_len; @@ -1402,21 +1419,45 @@ static bool fill_texpaint_slots_cb(bNode *node, void *userdata) ma->paint_active_slot = index; } - ma->texpaintslot[index].ima = (Image *)node->id; - ma->texpaintslot[index].interp = ((NodeTexImage *)node->storage)->interpolation; + switch (node->type) { + case SH_NODE_TEX_IMAGE: { + TexPaintSlot *slot = &ma->texpaintslot[index]; + slot->ima = (Image *)node->id; + slot->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); - /* 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; + slot->uvname = storage->uv_map; + /* set a value to index so UI knows that we have a valid pointer for the mesh */ + slot->valid = true; + } + else { + /* just invalidate the index here so UV map does not get displayed on the UI */ + slot->valid = false; + } + break; + } - 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; + case SH_NODE_ATTRIBUTE: { + TexPaintSlot *slot = &ma->texpaintslot[index]; + NodeShaderAttribute *storage = node->storage; + slot->attribute_name = storage->name; + if (storage->type == SHD_ATTRIBUTE_GEOMETRY) { + const Mesh *mesh = (const Mesh *)fill_data->ob->data; + CustomDataLayer *layer = BKE_id_attributes_color_find(&mesh->id, storage->name); + slot->valid = layer != NULL; + } + + /* Do not show unsupported attributes. */ + if (!slot->valid) { + slot->attribute_name = NULL; + fill_data->index--; + } + + break; + } } return fill_data->index != fill_data->slot_len; @@ -1424,14 +1465,26 @@ static bool fill_texpaint_slots_cb(bNode *node, void *userdata) static void fill_texpaint_slots_recursive(bNodeTree *nodetree, bNode *active_node, + const Object *ob, Material *ma, - int slot_len) + int slot_len, + ePaintSlotFilter slot_filter) +{ + struct FillTexPaintSlotsData fill_data = {active_node, ob, ma, 0, slot_len}; + ntree_foreach_texnode_recursive(nodetree, fill_texpaint_slots_cb, &fill_data, slot_filter); +} + +/** Check which type of paint slots should be filled for the given object. */ +static ePaintSlotFilter material_paint_slot_filter(const struct Object *ob) { - struct FillTexPaintSlotsData fill_data = {active_node, ma, 0, slot_len}; - ntree_foreach_texnode_recursive(nodetree, fill_texpaint_slots_cb, &fill_data); + ePaintSlotFilter slot_filter = PAINT_SLOT_IMAGE; + if (ob->mode == OB_MODE_SCULPT && U.experimental.use_sculpt_texture_paint) { + slot_filter |= PAINT_SLOT_COLOR_ATTRIBUTE; + } + return slot_filter; } -void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) +void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma, const struct Object *ob) { int count = 0; @@ -1439,6 +1492,8 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) return; } + const ePaintSlotFilter slot_filter = material_paint_slot_filter(ob); + /* 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); @@ -1460,7 +1515,7 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) return; } - count = count_texture_nodes_recursive(ma->nodetree); + count = count_texture_nodes_recursive(ma->nodetree, slot_filter); if (count == 0) { ma->paint_active_slot = 0; @@ -1470,9 +1525,9 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); - bNode *active_node = nodeGetActiveTexture(ma->nodetree); + bNode *active_node = nodeGetActivePaintCanvas(ma->nodetree); - fill_texpaint_slots_recursive(ma->nodetree, active_node, ma, count); + fill_texpaint_slots_recursive(ma->nodetree, active_node, ob, ma, count, slot_filter); ma->tot_slots = count; @@ -1489,22 +1544,32 @@ void BKE_texpaint_slots_refresh_object(Scene *scene, struct Object *ob) { for (int i = 1; i < ob->totcol + 1; i++) { Material *ma = BKE_object_material_get(ob, i); - BKE_texpaint_slot_refresh_cache(scene, ma); + BKE_texpaint_slot_refresh_cache(scene, ma, ob); } } struct FindTexPaintNodeData { - Image *ima; + TexPaintSlot *slot; bNode *r_node; }; static bool texpaint_slot_node_find_cb(bNode *node, void *userdata) { struct FindTexPaintNodeData *find_data = userdata; - Image *ima = (Image *)node->id; - if (find_data->ima == ima) { - find_data->r_node = node; - return false; + if (find_data->slot->ima && node->type == SH_NODE_TEX_IMAGE) { + Image *node_ima = (Image *)node->id; + if (find_data->slot->ima == node_ima) { + find_data->r_node = node; + return false; + } + } + + if (find_data->slot->attribute_name && node->type == SH_NODE_ATTRIBUTE) { + NodeShaderAttribute *storage = node->storage; + if (STREQLEN(find_data->slot->attribute_name, storage->name, sizeof(storage->name))) { + find_data->r_node = node; + return false; + } } return true; @@ -1512,8 +1577,12 @@ static bool texpaint_slot_node_find_cb(bNode *node, void *userdata) bNode *BKE_texpaint_slot_material_find_node(Material *ma, short texpaint_slot) { - struct FindTexPaintNodeData find_data = {ma->texpaintslot[texpaint_slot].ima, NULL}; - ntree_foreach_texnode_recursive(ma->nodetree, texpaint_slot_node_find_cb, &find_data); + TexPaintSlot *slot = &ma->texpaintslot[texpaint_slot]; + struct FindTexPaintNodeData find_data = {slot, NULL}; + ntree_foreach_texnode_recursive(ma->nodetree, + texpaint_slot_node_find_cb, + &find_data, + PAINT_SLOT_IMAGE | PAINT_SLOT_COLOR_ATTRIBUTE); return find_data.r_node; } diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index 76b66beaf0d..7efdd855a04 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -3610,19 +3610,17 @@ void nodeClearActive(bNodeTree *ntree) void nodeSetActive(bNodeTree *ntree, bNode *node) { - /* make sure only one node is active, and only one per ID type */ - LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) { - tnode->flag &= ~NODE_ACTIVE; + const bool is_paint_canvas = nodeSupportsActiveFlag(node, NODE_ACTIVE_PAINT_CANVAS); + const bool is_texture_class = nodeSupportsActiveFlag(node, NODE_ACTIVE_TEXTURE); + int flags_to_set = NODE_ACTIVE; + SET_FLAG_FROM_TEST(flags_to_set, is_paint_canvas, NODE_ACTIVE_PAINT_CANVAS); + SET_FLAG_FROM_TEST(flags_to_set, is_texture_class, NODE_ACTIVE_TEXTURE); - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { - tnode->flag &= ~NODE_ACTIVE_TEXTURE; - } - } - - node->flag |= NODE_ACTIVE; - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE) { - node->flag |= NODE_ACTIVE_TEXTURE; + /* Make sure only one node is active per node tree. */ + LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) { + tnode->flag &= ~flags_to_set; } + node->flag |= flags_to_set; } int nodeSocketIsHidden(const bNodeSocket *sock) diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 8e87f6ea243..eb3f47760fc 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -42,6 +42,7 @@ #include "BKE_key.h" #include "BKE_lib_id.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" @@ -1769,6 +1770,12 @@ static void sculpt_update_object(Depsgraph *depsgraph, } } } + + /* We could be more precise when we have access to the active tool. */ + const bool use_paint_slots = (ob->mode & OB_MODE_SCULPT) != 0; + if (use_paint_slots) { + BKE_texpaint_slots_refresh_object(scene, ob); + } } void BKE_sculpt_update_object_before_eval(Object *ob) |