UI: Add color attribute create to canvas selector

The purpose of this patch is to add the option to create a color
attribute paint slot from the canvas selector when in material mode.

See the discussion here: T97346

---
|Add Image Paint Slot|Add Color Attribute Paint Slot|
|{F13016547 size=full}|{F13032911 size=full}|

Reviewed By: HooglyBoogly, joeedh

Differential Revision: https://developer.blender.org/D14724
This commit is contained in:
Ethan-Hall 2022-05-09 08:21:22 +02:00 committed by Jeroen Bakker
parent 90298c24a2
commit b96cdbcf7a
Notes: blender-bot 2023-02-14 08:38:14 +01:00
Referenced by commit 719c86c0a6, Fix: compiler warnings due to recent commit
Referenced by issue #97346, Canvas Selector UX: Add option to create a color attribute in material mode.
1 changed files with 175 additions and 20 deletions

View File

@ -7,6 +7,7 @@
*/
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@ -35,12 +36,17 @@
#include "IMB_imbuf_types.h"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_defs.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_node_types.h"
#include "DNA_object_enums.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_attribute.h"
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_colorband.h"
@ -61,6 +67,8 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@ -76,12 +84,18 @@
#include "GPU_capabilities.h"
#include "GPU_init_exit.h"
#include "NOD_shader.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "WM_api.h"
#include "WM_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "RNA_types.h"
#include "IMB_colormanagement.h"
@ -6459,6 +6473,38 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data)
return ima;
}
static CustomDataLayer *proj_paint_color_attribute_create(wmOperator *op, Object *ob)
{
char name[MAX_NAME] = "";
float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
AttributeDomain domain = ATTR_DOMAIN_POINT;
CustomDataType type = CD_PROP_COLOR;
if (op) {
RNA_string_get(op->ptr, "name", name);
RNA_float_get_array(op->ptr, "color", color);
domain = (AttributeDomain)RNA_enum_get(op->ptr, "domain");
type = (CustomDataType)RNA_enum_get(op->ptr, "data_type");
}
ID *id = (ID *)ob->data;
CustomDataLayer *layer = BKE_id_attribute_new(id, name, type, domain, op->reports);
if (!layer) {
return NULL;
}
BKE_id_attributes_active_color_set(id, layer);
if (!BKE_id_attributes_render_color_get(id)) {
BKE_id_attributes_render_color_set(id, layer);
}
BKE_object_attributes_active_color_fill(ob, color, false);
return layer;
}
static void proj_paint_default_color(wmOperator *op, int type, Material *ma)
{
if (RNA_struct_property_is_set(op->ptr, "color")) {
@ -6516,6 +6562,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Material *ma;
Image *ima = NULL;
CustomDataLayer *layer = NULL;
if (!ob) {
return false;
@ -6528,7 +6575,7 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
int type = RNA_enum_get(op->ptr, "type");
bool is_data = (type > LAYER_BASE_COLOR);
bNode *imanode;
bNode *new_node;
bNodeTree *ntree = ma->nodetree;
if (!ntree) {
@ -6538,17 +6585,33 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
ma->use_nodes = true;
/* try to add an image node */
imanode = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
const ePaintCanvasSource slot_type = ob->mode == OB_MODE_SCULPT ?
(ePaintCanvasSource)RNA_enum_get(op->ptr,
"slot_type") :
PAINT_CANVAS_SOURCE_IMAGE;
ima = proj_paint_image_create(op, bmain, is_data);
imanode->id = &ima->id;
nodeSetActive(ntree, imanode);
/* Create a new node. */
switch (slot_type) {
case PAINT_CANVAS_SOURCE_IMAGE: {
new_node = nodeAddStaticNode(C, ntree, SH_NODE_TEX_IMAGE);
ima = proj_paint_image_create(op, bmain, is_data);
new_node->id = &ima->id;
break;
}
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE: {
new_node = nodeAddStaticNode(C, ntree, SH_NODE_ATTRIBUTE);
if (layer = proj_paint_color_attribute_create(op, ob)) {
BLI_strncpy_utf8(
&((NodeShaderAttribute *)new_node->storage)->name, &layer->name, MAX_NAME);
}
break;
}
}
nodeSetActive(ntree, new_node);
/* Connect to first available principled BSDF node. */
bNode *in_node = ntreeFindType(ntree, SH_NODE_BSDF_PRINCIPLED);
bNode *out_node = imanode;
bNode *out_node = new_node;
if (in_node != NULL) {
bNodeSocket *out_sock = nodeFindSocket(out_node, SOCK_OUT, "Color");
@ -6611,6 +6674,11 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
}
if (layer) {
BKE_texpaint_slot_refresh_cache(scene, ma, ob);
DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
}
DEG_id_tag_update(&ntree->id, 0);
DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
@ -6678,13 +6746,48 @@ static int texture_paint_add_texture_paint_slot_invoke(bContext *C,
int type = get_texture_layer_type(op, "type");
proj_paint_default_color(op, type, ma);
char imagename[MAX_ID_NAME - 2];
get_default_texture_layer_name_for_object(ob, type, (char *)&imagename, sizeof(imagename));
RNA_string_set(op->ptr, "name", imagename);
char name[MAX_NAME];
get_default_texture_layer_name_for_object(ob, type, (char *)&name, sizeof(name));
RNA_string_set(op->ptr, "name", name);
return WM_operator_props_dialog_popup(C, op, 300);
}
static void texture_paint_add_texture_paint_slot_ui(bContext *C, wmOperator *op)
{
uiLayout *layout = op->layout;
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
Object *ob = ED_object_active_context(C);
ePaintCanvasSource slot_type = PAINT_CANVAS_SOURCE_IMAGE;
if (ob->mode == OB_MODE_SCULPT) {
slot_type = (ePaintCanvasSource)RNA_enum_get(op->ptr, "slot_type");
uiItemR(layout, op->ptr, "slot_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
}
uiItemR(layout, op->ptr, "name", 0, NULL, ICON_NONE);
switch (slot_type) {
case PAINT_CANVAS_SOURCE_IMAGE: {
uiLayout *col = uiLayoutColumn(layout, true);
uiItemR(col, op->ptr, "width", 0, NULL, ICON_NONE);
uiItemR(col, op->ptr, "height", 0, NULL, ICON_NONE);
uiItemR(layout, op->ptr, "alpha", 0, NULL, ICON_NONE);
uiItemR(layout, op->ptr, "generated_type", 0, NULL, ICON_NONE);
uiItemR(layout, op->ptr, "float", 0, NULL, ICON_NONE);
break;
}
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
uiItemR(layout, op->ptr, "domain", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemR(layout, op->ptr, "data_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
break;
}
uiItemR(layout, op->ptr, "color", 0, NULL, ICON_NONE);
}
#define IMA_DEF_NAME N_("Untitled")
void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
@ -6692,40 +6795,92 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
PropertyRNA *prop;
static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
static const EnumPropertyItem slot_type_items[3] = {
{PAINT_CANVAS_SOURCE_IMAGE, "IMAGE", 0, "Image", ""},
{PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE, "COLOR_ATTRIBUTE", 0, "Color Attribute", ""},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem domain_items[3] = {
{ATTR_DOMAIN_POINT, "POINT", 0, "Vertex", ""},
{ATTR_DOMAIN_CORNER, "CORNER", 0, "Face Corner", ""},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem attribute_type_items[3] = {
{CD_PROP_COLOR, "COLOR", 0, "Color", ""},
{CD_PROP_BYTE_COLOR, "BYTE_COLOR", 0, "Byte Color", ""},
{0, NULL, 0, NULL, NULL},
};
/* identifiers */
ot->name = "Add Texture Paint Slot";
ot->description = "Add a texture paint slot";
ot->name = "Add Paint Slot";
ot->description = "Add a paint slot";
ot->idname = "PAINT_OT_add_texture_paint_slot";
/* api callbacks */
ot->invoke = texture_paint_add_texture_paint_slot_invoke;
ot->exec = texture_paint_add_texture_paint_slot_exec;
ot->poll = ED_operator_object_active_editable_mesh;
ot->ui = texture_paint_add_texture_paint_slot_ui;
/* flags */
ot->flag = OPTYPE_UNDO;
/* properties */
prop = RNA_def_enum(ot->srna, "type", layer_type_items, 0, "Type", "Merge method to use");
/* Shared Properties */
prop = RNA_def_enum(ot->srna,
"type",
layer_type_items,
0,
"Material Layer Type",
"Material layer type of new paint slot");
RNA_def_property_flag(prop, PROP_HIDDEN);
RNA_def_string(ot->srna, "name", IMA_DEF_NAME, MAX_ID_NAME - 2, "Name", "Image data-block name");
prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
RNA_def_property_subtype(prop, PROP_PIXEL);
prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
RNA_def_property_subtype(prop, PROP_PIXEL);
prop = RNA_def_enum(
ot->srna, "slot_type", slot_type_items, 0, "Slot Type", "Type of new paint slot");
prop = RNA_def_string(
ot->srna, "name", IMA_DEF_NAME, MAX_NAME, "Name", "Name for new paint slot source");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_float_color(
ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
RNA_def_property_float_array_default(prop, default_color);
/* Image Properties */
prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
RNA_def_property_subtype(prop, PROP_PIXEL);
prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
RNA_def_property_subtype(prop, PROP_PIXEL);
RNA_def_boolean(ot->srna, "alpha", true, "Alpha", "Create an image with an alpha channel");
RNA_def_enum(ot->srna,
"generated_type",
rna_enum_image_generated_type_items,
IMA_GENTYPE_BLANK,
"Generated Type",
"Fill the image with a grid for UV map testing");
RNA_def_boolean(
ot->srna, "float", 0, "32-bit Float", "Create image with 32-bit floating-point bit depth");
/* Color Attribute Properties */
RNA_def_enum(ot->srna,
"domain",
domain_items,
ATTR_DOMAIN_POINT,
"Domain",
"Type of element that attribute is stored on");
RNA_def_enum(ot->srna,
"data_type",
attribute_type_items,
CD_PROP_COLOR,
"Data Type",
"Type of data stored in attribute");
}
static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))