Compare commits
55 Commits
temp-nodes
...
temp-T9670
Author | SHA1 | Date | |
---|---|---|---|
d466b0378a | |||
c71027705c | |||
15aea1bb22 | |||
d6a741ae83 | |||
da172ea0f6 | |||
8648d7145f | |||
9fe81c4719 | |||
ece878018f | |||
b7c46bb7fa | |||
26910f68ad | |||
2878a75e82 | |||
3e095d3495 | |||
66a3a589fa | |||
a327d98d3c | |||
82863e94c9 | |||
b9c48323b6 | |||
7bf8459c13 | |||
ce0a5a435e | |||
f71609fe59 | |||
8323541a05 | |||
5c22f28334 | |||
3b4031718a | |||
821d389da4 | |||
5e2bb3eed2 | |||
c25d986111 | |||
f4792e6801 | |||
9644f3acfb | |||
6231a4ce24 | |||
17125fb75d | |||
40e27448b3 | |||
9a6dcc340b | |||
c5de824d82 | |||
a92219b2f3 | |||
79a7d38c4c | |||
8ba7440aec | |||
6f0dfb2448 | |||
5a33f6be4f | |||
a87f9f8081 | |||
2fff10e2bf | |||
a38d07223e | |||
3bd3bc7122 | |||
36e6b4d32a | |||
cc8dfac9a9 | |||
5ef083cd3a | |||
69ead4b848 | |||
22ea079310 | |||
42c5fd505e | |||
0fc46d05e5 | |||
6a8bd6e598 | |||
a8993dd12a | |||
66d0b1b5c3 | |||
08297586ed | |||
b8d7bbd15b | |||
1ae8622d47 | |||
fb76179758 |
@@ -565,7 +565,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
|
||||
layout.label(text="Name collisions: " + ", ".join(set(colliding_names)), icon='ERROR')
|
||||
|
||||
|
||||
class MESH_UL_color_attributes(UIList):
|
||||
class ColorAttributesListBase():
|
||||
display_domain_names = {
|
||||
'POINT': "Vertex",
|
||||
'EDGE': "Edge",
|
||||
@@ -588,6 +588,8 @@ class MESH_UL_color_attributes(UIList):
|
||||
|
||||
return ret, idxs
|
||||
|
||||
|
||||
class MESH_UL_color_attributes(UIList, ColorAttributesListBase):
|
||||
def draw_item(self, _context, layout, data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
|
||||
|
||||
@@ -613,6 +615,12 @@ class MESH_UL_color_attributes(UIList):
|
||||
sub.label(text="%s ▶ %s" % (domain_name, data_type.name))
|
||||
|
||||
|
||||
class MESH_UL_color_attributes_selector(UIList, ColorAttributesListBase):
|
||||
def draw_item(self, _context, layout, data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
layout.emboss = 'NONE'
|
||||
layout.prop(attribute, "name", text="", icon='COLOR')
|
||||
|
||||
|
||||
class DATA_PT_vertex_colors(DATA_PT_mesh_attributes, Panel):
|
||||
bl_label = "Color Attributes"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -663,6 +671,7 @@ classes = (
|
||||
DATA_PT_customdata,
|
||||
DATA_PT_custom_props_mesh,
|
||||
MESH_UL_color_attributes,
|
||||
MESH_UL_color_attributes_selector,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
|
@@ -238,7 +238,7 @@ class ClonePanel(BrushPanel):
|
||||
col.label(text="Source Clone Slot")
|
||||
col.template_list(
|
||||
"TEXTURE_UL_texpaintslots", "",
|
||||
mat, "texture_paint_images",
|
||||
mat, "texture_paint_slots",
|
||||
mat, "paint_clone_slot",
|
||||
rows=2,
|
||||
)
|
||||
|
@@ -280,7 +280,7 @@ class TEXTURE_UL_texpaintslots(UIList):
|
||||
# mat = data
|
||||
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
|
||||
layout.prop(item, "name", text="", emboss=False, icon_value=item.icon_value)
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="")
|
||||
@@ -459,15 +459,11 @@ class VIEW3D_MT_tools_projectpaint_uvlayer(Menu):
|
||||
props.value = i
|
||||
|
||||
|
||||
class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
|
||||
class SelectPaintSlotHelper:
|
||||
bl_category = "Tool"
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
bl_label = "Texture Slots"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.image_paint.brush
|
||||
return (brush is not None and context.active_object is not None)
|
||||
canvas_source_attr_name = "canvas_source"
|
||||
canvas_image_attr_name = "canvas_image"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -475,51 +471,66 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
|
||||
layout.use_property_decorate = False
|
||||
|
||||
settings = context.tool_settings.image_paint
|
||||
mode_settings = self.get_mode_settings(context)
|
||||
|
||||
ob = context.active_object
|
||||
|
||||
layout.prop(settings, "mode", text="Mode")
|
||||
layout.prop(mode_settings, self.canvas_source_attr_name, text="Mode")
|
||||
layout.separator()
|
||||
|
||||
if settings.mode == 'MATERIAL':
|
||||
if len(ob.material_slots) > 1:
|
||||
layout.template_list("MATERIAL_UL_matslots", "layers",
|
||||
ob, "material_slots",
|
||||
ob, "active_material_index", rows=2)
|
||||
mat = ob.active_material
|
||||
if mat and mat.texture_paint_images:
|
||||
row = layout.row()
|
||||
row.template_list("TEXTURE_UL_texpaintslots", "",
|
||||
mat, "texture_paint_images",
|
||||
mat, "paint_active_slot", rows=2)
|
||||
have_image = False
|
||||
|
||||
if mat.texture_paint_slots:
|
||||
slot = mat.texture_paint_slots[mat.paint_active_slot]
|
||||
match getattr(mode_settings, self.canvas_source_attr_name):
|
||||
case 'MATERIAL':
|
||||
if len(ob.material_slots) > 1:
|
||||
layout.template_list("MATERIAL_UL_matslots", "layers",
|
||||
ob, "material_slots",
|
||||
ob, "active_material_index", rows=2)
|
||||
mat = ob.active_material
|
||||
if mat and mat.texture_paint_images:
|
||||
row = layout.row()
|
||||
row.template_list("TEXTURE_UL_texpaintslots", "",
|
||||
mat, "texture_paint_slots",
|
||||
mat, "paint_active_slot", rows=2)
|
||||
|
||||
if mat.texture_paint_slots:
|
||||
slot = mat.texture_paint_slots[mat.paint_active_slot]
|
||||
else:
|
||||
slot = None
|
||||
|
||||
have_image = slot is not None
|
||||
else:
|
||||
slot = None
|
||||
row = layout.row()
|
||||
|
||||
have_image = slot is not None
|
||||
else:
|
||||
row = layout.row()
|
||||
box = row.box()
|
||||
box.label(text="No Textures")
|
||||
|
||||
box = row.box()
|
||||
box.label(text="No Textures")
|
||||
have_image = False
|
||||
sub = row.column(align=True)
|
||||
sub.operator_menu_enum("paint.add_texture_paint_slot", "type", icon='ADD', text="")
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.operator_menu_enum("paint.add_texture_paint_slot", "type", icon='ADD', text="")
|
||||
case 'IMAGE':
|
||||
mesh = ob.data
|
||||
uv_text = mesh.uv_layers.active.name if mesh.uv_layers.active else ""
|
||||
layout.template_ID(mode_settings, self.canvas_image_attr_name, new="image.new", open="image.open")
|
||||
if settings.missing_uvs:
|
||||
layout.operator("paint.add_simple_uvs", icon='ADD', text="Add UVs")
|
||||
else:
|
||||
layout.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
|
||||
have_image = getattr(settings, self.canvas_image_attr_name) is not None
|
||||
|
||||
self.draw_image_interpolation(layout=layout, mode_settings=mode_settings)
|
||||
|
||||
elif settings.mode == 'IMAGE':
|
||||
mesh = ob.data
|
||||
uv_text = mesh.uv_layers.active.name if mesh.uv_layers.active else ""
|
||||
layout.template_ID(settings, "canvas", new="image.new", open="image.open")
|
||||
if settings.missing_uvs:
|
||||
layout.operator("paint.add_simple_uvs", icon='ADD', text="Add UVs")
|
||||
else:
|
||||
layout.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
|
||||
have_image = settings.canvas is not None
|
||||
|
||||
layout.prop(settings, "interpolation", text="")
|
||||
case 'COLOR_ATTRIBUTE':
|
||||
mesh = ob.data
|
||||
layout.template_list(
|
||||
"MESH_UL_color_attributes_selector",
|
||||
"color_attributes",
|
||||
mesh,
|
||||
"color_attributes",
|
||||
mesh.color_attributes,
|
||||
"active_color_index",
|
||||
rows=3,
|
||||
)
|
||||
|
||||
if settings.missing_uvs:
|
||||
layout.separator()
|
||||
@@ -531,6 +542,50 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
|
||||
layout.operator("image.save_all_modified", text="Save All Images", icon='FILE_TICK')
|
||||
|
||||
|
||||
class VIEW3D_PT_slots_projectpaint(SelectPaintSlotHelper, View3DPanel, Panel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
bl_label = "Texture Slots"
|
||||
|
||||
canvas_source_attr_name = "mode"
|
||||
canvas_image_attr_name = "canvas"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
brush = context.tool_settings.image_paint.brush
|
||||
return (brush is not None and context.active_object is not None)
|
||||
|
||||
def get_mode_settings(self, context):
|
||||
return context.tool_settings.image_paint
|
||||
|
||||
def draw_image_interpolation(self, layout, mode_settings):
|
||||
layout.prop(mode_settings, "interpolation", text="")
|
||||
|
||||
|
||||
|
||||
class VIEW3D_PT_slots_paint_canvas(SelectPaintSlotHelper, View3DPanel, Panel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
bl_label = "Canvas"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if not context.preferences.experimental.use_sculpt_texture_paint:
|
||||
return False
|
||||
|
||||
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
|
||||
tool = ToolSelectPanelHelper.tool_active_from_context(context)
|
||||
if tool is None:
|
||||
return False
|
||||
return tool.use_paint_canvas
|
||||
|
||||
def get_mode_settings(self, context):
|
||||
return context.tool_settings.paint_mode
|
||||
|
||||
def draw_image_interpolation(self, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class VIEW3D_PT_mask(View3DPanel, Panel):
|
||||
bl_category = "Tool"
|
||||
bl_context = ".imagepaint" # dot on purpose (access from topbar)
|
||||
@@ -2232,6 +2287,7 @@ classes = (
|
||||
VIEW3D_PT_tools_posemode_options,
|
||||
|
||||
VIEW3D_PT_slots_projectpaint,
|
||||
VIEW3D_PT_slots_paint_canvas,
|
||||
VIEW3D_PT_tools_brush_select,
|
||||
VIEW3D_PT_tools_brush_settings,
|
||||
VIEW3D_PT_tools_brush_color,
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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, ma, 0, slot_len};
|
||||
ntree_foreach_texnode_recursive(nodetree, fill_texpaint_slots_cb, &fill_data);
|
||||
struct FillTexPaintSlotsData fill_data = {active_node, ob, ma, 0, slot_len};
|
||||
ntree_foreach_texnode_recursive(nodetree, fill_texpaint_slots_cb, &fill_data, slot_filter);
|
||||
}
|
||||
|
||||
void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
|
||||
/** Check which type of paint slots should be filled for the given object. */
|
||||
static ePaintSlotFilter material_paint_slot_filter(const struct Object *ob)
|
||||
{
|
||||
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, 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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
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);
|
||||
|
||||
/* Make sure only one node is active per node tree. */
|
||||
LISTBASE_FOREACH (bNode *, tnode, &ntree->nodes) {
|
||||
tnode->flag &= ~NODE_ACTIVE;
|
||||
|
||||
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;
|
||||
tnode->flag &= ~flags_to_set;
|
||||
}
|
||||
node->flag |= flags_to_set;
|
||||
}
|
||||
|
||||
int nodeSocketIsHidden(const bNodeSocket *sock)
|
||||
|
@@ -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)
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "ED_paint.h"
|
||||
|
||||
#include "workbench_engine.h"
|
||||
#include "workbench_private.h"
|
||||
|
||||
@@ -94,8 +96,6 @@ static void workbench_cache_sculpt_populate(WORKBENCH_PrivateData *wpd,
|
||||
eV3DShadingColorType color_type)
|
||||
{
|
||||
const bool use_single_drawcall = !ELEM(color_type, V3D_SHADING_MATERIAL_COLOR);
|
||||
BLI_assert(color_type != V3D_SHADING_TEXTURE_COLOR);
|
||||
|
||||
if (use_single_drawcall) {
|
||||
DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, NULL);
|
||||
DRW_shgroup_call_sculpt(grp, ob, false, false);
|
||||
@@ -324,6 +324,16 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
|
||||
color_type = V3D_SHADING_MATERIAL_COLOR;
|
||||
}
|
||||
|
||||
if (is_sculpt_pbvh) {
|
||||
/* Bad call C is required to access the tool system that is context aware. Cast to non-const
|
||||
* due to current API. */
|
||||
bContext *C = (bContext *)DRW_context_state_get()->evil_C;
|
||||
if (C != NULL) {
|
||||
color_type = ED_paint_shading_color_override(
|
||||
C, &wpd->scene->toolsettings->paint_mode, ob, color_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (r_draw_shadow) {
|
||||
*r_draw_shadow = (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 && SHADOW_ENABLED(wpd);
|
||||
/* Currently unsupported in sculpt mode. We could revert to the slow
|
||||
|
@@ -6,10 +6,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_view3d_enums.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct PaintModeSettings;
|
||||
struct ImBuf;
|
||||
struct Image;
|
||||
struct ImageUser;
|
||||
@@ -109,6 +112,28 @@ void ED_paintcurve_undo_push_end(struct bContext *C);
|
||||
/** Export for ED_undo_sys. */
|
||||
void ED_paintcurve_undosys_type(struct UndoType *ut);
|
||||
|
||||
/* paint_canvas.cc */
|
||||
struct Image *ED_paint_canvas_image_get(const struct PaintModeSettings *settings,
|
||||
struct Object *ob);
|
||||
int ED_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *settings,
|
||||
struct Object *ob);
|
||||
|
||||
/** Color type of an object can be overridden in sculpt/paint mode. */
|
||||
eV3DShadingColorType ED_paint_shading_color_override(struct bContext *C,
|
||||
const struct PaintModeSettings *settings,
|
||||
struct Object *ob,
|
||||
eV3DShadingColorType orig_color_type);
|
||||
|
||||
/**
|
||||
* Does the given tool use a paint canvas.
|
||||
*
|
||||
* When #tref isn't given the active tool from the context is used.
|
||||
*/
|
||||
bool ED_paint_tool_use_canvas(struct bContext *C, struct bToolRef *tref);
|
||||
|
||||
/* Store the last used tool in the sculpt session. */
|
||||
void ED_paint_tool_update_sticky_shading_color(struct bContext *C, struct Object *ob);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@@ -34,6 +34,7 @@ set(SRC
|
||||
curves_sculpt_grow_shrink.cc
|
||||
curves_sculpt_ops.cc
|
||||
curves_sculpt_snake_hook.cc
|
||||
paint_canvas.cc
|
||||
paint_cursor.c
|
||||
paint_curve.c
|
||||
paint_curve_undo.c
|
||||
|
203
source/blender/editors/sculpt_paint/paint_canvas.cc
Normal file
203
source/blender/editors/sculpt_paint/paint_canvas.cc
Normal file
@@ -0,0 +1,203 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#include "BLI_compiler_compat.h"
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_pbvh.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "NOD_shader.h"
|
||||
|
||||
#include "WM_toolsystem.h"
|
||||
|
||||
namespace blender::ed::sculpt_paint::canvas {
|
||||
static TexPaintSlot *get_active_slot(Object *ob)
|
||||
{
|
||||
Material *mat = BKE_object_material_get(ob, ob->actcol);
|
||||
if (mat == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (mat->texpaintslot == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (mat->paint_active_slot >= mat->tot_slots) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TexPaintSlot *slot = &mat->texpaintslot[mat->paint_active_slot];
|
||||
return slot;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::sculpt_paint::canvas
|
||||
|
||||
extern "C" {
|
||||
|
||||
using namespace blender;
|
||||
using namespace blender::ed::sculpt_paint::canvas;
|
||||
|
||||
/* Does the paint tool with the given idname uses a canvas. */
|
||||
static bool paint_tool_uses_canvas(StringRef idname)
|
||||
{
|
||||
return ELEM(idname, "builtin_brush.Paint", "builtin_brush.Smear", "builtin.color_filter");
|
||||
}
|
||||
|
||||
static bool paint_tool_shading_color_follows_last_used(StringRef idname)
|
||||
{
|
||||
/* TODO(jbakker): complete this list. */
|
||||
return ELEM(idname, "builtin_brush.Mask");
|
||||
}
|
||||
|
||||
void ED_paint_tool_update_sticky_shading_color(struct bContext *C, struct Object *ob)
|
||||
{
|
||||
if (ob == nullptr || ob->sculpt == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
bToolRef *tref = WM_toolsystem_ref_from_context(C);
|
||||
if (tref == nullptr) {
|
||||
return;
|
||||
}
|
||||
/* Do not modify when tool follows lat used tool. */
|
||||
if (paint_tool_shading_color_follows_last_used(tref->idname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ob->sculpt->sticky_shading_color = paint_tool_uses_canvas(tref->idname);
|
||||
}
|
||||
|
||||
static bool paint_tool_shading_color_follows_last_used_tool(struct bContext *C, struct Object *ob)
|
||||
{
|
||||
if (ob == nullptr || ob->sculpt == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bToolRef *tref = WM_toolsystem_ref_from_context(C);
|
||||
if (tref == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return paint_tool_shading_color_follows_last_used(tref->idname);
|
||||
}
|
||||
|
||||
bool ED_paint_tool_use_canvas(struct bContext *C, bToolRef *tref)
|
||||
{
|
||||
if (tref == nullptr) {
|
||||
tref = WM_toolsystem_ref_from_context(C);
|
||||
}
|
||||
if (tref == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return paint_tool_uses_canvas(tref->idname);
|
||||
}
|
||||
|
||||
eV3DShadingColorType ED_paint_shading_color_override(bContext *C,
|
||||
const PaintModeSettings *settings,
|
||||
Object *ob,
|
||||
eV3DShadingColorType orig_color_type)
|
||||
{
|
||||
if (!U.experimental.use_sculpt_texture_paint) {
|
||||
return orig_color_type;
|
||||
}
|
||||
/* NOTE: This early exit is temporarily, until a paint mode has been added.
|
||||
* For better integration with the vertex paint in sculpt mode we sticky
|
||||
* with the last stoke when using tools like masking.
|
||||
*/
|
||||
if (!ED_paint_tool_use_canvas(C, nullptr) &&
|
||||
!(paint_tool_shading_color_follows_last_used_tool(C, ob) &&
|
||||
ob->sculpt->sticky_shading_color)) {
|
||||
return orig_color_type;
|
||||
}
|
||||
|
||||
eV3DShadingColorType color_type = orig_color_type;
|
||||
switch (settings->canvas_source) {
|
||||
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
|
||||
color_type = V3D_SHADING_VERTEX_COLOR;
|
||||
break;
|
||||
case PAINT_CANVAS_SOURCE_IMAGE:
|
||||
color_type = V3D_SHADING_TEXTURE_COLOR;
|
||||
break;
|
||||
case PAINT_CANVAS_SOURCE_MATERIAL: {
|
||||
TexPaintSlot *slot = get_active_slot(ob);
|
||||
if (slot == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (slot->ima) {
|
||||
color_type = V3D_SHADING_TEXTURE_COLOR;
|
||||
}
|
||||
if (slot->attribute_name) {
|
||||
color_type = V3D_SHADING_VERTEX_COLOR;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return color_type;
|
||||
}
|
||||
|
||||
Image *ED_paint_canvas_image_get(const struct PaintModeSettings *settings, struct Object *ob)
|
||||
{
|
||||
switch (settings->canvas_source) {
|
||||
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
|
||||
return nullptr;
|
||||
case PAINT_CANVAS_SOURCE_IMAGE:
|
||||
return settings->canvas_image;
|
||||
case PAINT_CANVAS_SOURCE_MATERIAL: {
|
||||
TexPaintSlot *slot = get_active_slot(ob);
|
||||
if (slot == nullptr) {
|
||||
break;
|
||||
}
|
||||
return slot->ima;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int ED_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *settings,
|
||||
struct Object *ob)
|
||||
{
|
||||
switch (settings->canvas_source) {
|
||||
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
|
||||
return -1;
|
||||
case PAINT_CANVAS_SOURCE_IMAGE: {
|
||||
/* Use active uv map of the object. */
|
||||
if (ob->type != OB_MESH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
return CustomData_get_active_layer_index(&mesh->ldata, CD_MLOOPUV);
|
||||
}
|
||||
case PAINT_CANVAS_SOURCE_MATERIAL: {
|
||||
/* Use uv map of the canvas. */
|
||||
TexPaintSlot *slot = get_active_slot(ob);
|
||||
if (slot == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ob->type != OB_MESH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (slot->uvname == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Mesh *mesh = static_cast<Mesh *>(ob->data);
|
||||
return CustomData_get_named_layer_index(&mesh->ldata, CD_MLOOPUV, slot->uvname);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
@@ -6336,7 +6336,7 @@ bool ED_paint_proj_mesh_data_check(
|
||||
hasmat = true;
|
||||
if (ma->texpaintslot == NULL) {
|
||||
/* refresh here just in case */
|
||||
BKE_texpaint_slot_refresh_cache(scene, ma);
|
||||
BKE_texpaint_slot_refresh_cache(scene, ma, ob);
|
||||
}
|
||||
if (ma->texpaintslot != NULL &&
|
||||
(ma->texpaintslot[ma->paint_active_slot].ima == NULL ||
|
||||
@@ -6607,7 +6607,7 @@ 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(scene, ma, ob);
|
||||
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_USER_NEW_IMAGE);
|
||||
WM_event_add_notifier(C, NC_IMAGE | NA_ADDED, ima);
|
||||
}
|
||||
|
@@ -281,7 +281,7 @@ static void imapaint_pick_uv(
|
||||
float p[2], w[3], absw, minabsw;
|
||||
float matrix[4][4], proj[4][4];
|
||||
int view[4];
|
||||
const eImagePaintMode mode = scene->toolsettings->imapaint.mode;
|
||||
const ePaintCanvasSource mode = scene->toolsettings->imapaint.mode;
|
||||
|
||||
const MLoopTri *lt = BKE_mesh_runtime_looptri_ensure(me_eval);
|
||||
const int tottri = me_eval->runtime.looptris.len;
|
||||
@@ -317,7 +317,7 @@ static void imapaint_pick_uv(
|
||||
copy_v3_v3(tri_co[j], mvert[mloop[lt->tri[j]].v].co);
|
||||
}
|
||||
|
||||
if (mode == IMAGEPAINT_MODE_MATERIAL) {
|
||||
if (mode == PAINT_CANVAS_SOURCE_MATERIAL) {
|
||||
const Material *ma;
|
||||
const TexPaintSlot *slot;
|
||||
|
||||
@@ -431,7 +431,7 @@ void paint_sample_color(
|
||||
Material *ma = BKE_object_material_get(ob_eval, mp->mat_nr + 1);
|
||||
|
||||
/* Force refresh since paint slots are not updated when changing interpolation. */
|
||||
BKE_texpaint_slot_refresh_cache(scene, ma);
|
||||
BKE_texpaint_slot_refresh_cache(scene, ma, ob);
|
||||
|
||||
if (ma && ma->texpaintslot) {
|
||||
image = ma->texpaintslot[ma->paint_active_slot].ima;
|
||||
|
@@ -70,6 +70,7 @@
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_object.h"
|
||||
#include "ED_paint.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_sculpt.h"
|
||||
#include "ED_view3d.h"
|
||||
@@ -4991,6 +4992,8 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
|
||||
* earlier steps modifying the data. */
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, need_mask, needs_colors);
|
||||
|
||||
ED_paint_tool_update_sticky_shading_color(C, ob);
|
||||
}
|
||||
|
||||
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
|
||||
@@ -5191,6 +5194,8 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
|
||||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
/* NOTE: This should be removed when paint mode is available. Paint mode can force based on the
|
||||
* canvas it is painting on. (ref. use_sculpt_texture_paint). */
|
||||
if (brush && SCULPT_TOOL_NEEDS_COLOR(brush->sculpt_tool)) {
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d) {
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_object.h"
|
||||
#include "ED_paint.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_sculpt.h"
|
||||
#include "paint_intern.h"
|
||||
@@ -293,6 +294,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
|
||||
FilterCache *filter_cache = ss->filter_cache;
|
||||
filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
|
||||
filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
|
||||
ED_paint_tool_update_sticky_shading_color(C, ob);
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
|
@@ -1300,6 +1300,27 @@ static void view3d_main_region_listener(const wmRegionListenerParams *params)
|
||||
}
|
||||
}
|
||||
|
||||
static void view3d_do_msg_notify_workbench_view_update(struct bContext *C,
|
||||
struct wmMsgSubscribeKey *UNUSED(msg_key),
|
||||
struct wmMsgSubscribeValue *msg_val)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ScrArea *area = (ScrArea *)msg_val->user_data;
|
||||
View3D *v3d = (View3D *)area->spacedata.first;
|
||||
if (v3d->shading.type == OB_SOLID) {
|
||||
RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
|
||||
DRWUpdateContext drw_context = {NULL};
|
||||
drw_context.bmain = CTX_data_main(C);
|
||||
drw_context.depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
drw_context.scene = scene;
|
||||
drw_context.view_layer = CTX_data_view_layer(C);
|
||||
drw_context.region = (ARegion *)(msg_val->owner);
|
||||
drw_context.v3d = v3d;
|
||||
drw_context.engine_type = engine_type;
|
||||
DRW_notify_view_update(&drw_context);
|
||||
}
|
||||
}
|
||||
|
||||
static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params)
|
||||
{
|
||||
struct wmMsgBus *mbus = params->message_bus;
|
||||
@@ -1341,6 +1362,12 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP
|
||||
.notify = ED_region_do_msg_notify_tag_redraw,
|
||||
};
|
||||
|
||||
wmMsgSubscribeValue msg_sub_value_workbench_view_update = {
|
||||
.owner = region,
|
||||
.user_data = area,
|
||||
.notify = view3d_do_msg_notify_workbench_view_update,
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
|
||||
msg_key_params.ptr.type = type_array[i];
|
||||
WM_msg_subscribe_rna_params(mbus, &msg_key_params, &msg_sub_value_region_tag_redraw, __func__);
|
||||
@@ -1374,6 +1401,11 @@ static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeP
|
||||
case OB_MODE_PARTICLE_EDIT:
|
||||
WM_msg_subscribe_rna_anon_type(mbus, ParticleEdit, &msg_sub_value_region_tag_redraw);
|
||||
break;
|
||||
|
||||
case OB_MODE_SCULPT:
|
||||
WM_msg_subscribe_rna_anon_prop(
|
||||
mbus, WorkSpace, tools, &msg_sub_value_workbench_view_update);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -27,11 +27,16 @@ struct bNodeTree;
|
||||
/* WATCH IT: change type? also make changes in ipo.h */
|
||||
|
||||
typedef struct TexPaintSlot {
|
||||
/** Image to be painted on. */
|
||||
/** Image to be painted on. Mutual exclusive with attribute_name. */
|
||||
struct Image *ima;
|
||||
/** Custom-data index for uv layer, #MAX_NAME. */
|
||||
char *uvname;
|
||||
/** Do we have a valid image and UV map. */
|
||||
/**
|
||||
* Color attribute name when painting using color attributes. Mutual exclusive with ima.
|
||||
* Points to the name of a CustomDataLayer.
|
||||
*/
|
||||
char *attribute_name;
|
||||
/** Do we have a valid image and UV map or attribute. */
|
||||
int valid;
|
||||
/** Copy of node interpolation setting. */
|
||||
int interp;
|
||||
|
@@ -397,6 +397,8 @@ typedef struct bNode {
|
||||
#define NODE_DO_OUTPUT_RECALC (1 << 17)
|
||||
/* A preview for the data in this node can be displayed in the spreadsheet editor. */
|
||||
#define __NODE_ACTIVE_PREVIEW (1 << 18) /* deprecated */
|
||||
/* Active node that is used to paint on. */
|
||||
#define NODE_ACTIVE_PAINT_CANVAS (1 << 19)
|
||||
|
||||
/* node->update */
|
||||
#define NODE_UPDATE_ID 1 /* associated id data block has changed */
|
||||
|
@@ -929,6 +929,19 @@ typedef struct ImagePaintSettings {
|
||||
char _pad[4];
|
||||
} ImagePaintSettings;
|
||||
|
||||
/* ------------------------------------------- */
|
||||
/* Paint mode settings */
|
||||
|
||||
typedef struct PaintModeSettings {
|
||||
/** Source to select canvas from to paint on (ePaintCanvasSource) */
|
||||
char canvas_source;
|
||||
char _pad[7];
|
||||
|
||||
/** Selected image when canvas_source=PAINT_CANVAS_SOURCE_IMAGE. */
|
||||
Image *canvas_image;
|
||||
|
||||
} PaintModeSettings;
|
||||
|
||||
/* ------------------------------------------- */
|
||||
/* Particle Edit */
|
||||
|
||||
@@ -1462,6 +1475,9 @@ typedef struct ToolSettings {
|
||||
/* Image Paint (8 bytes aligned please!) */
|
||||
struct ImagePaintSettings imapaint;
|
||||
|
||||
/** Settings for paint mode. */
|
||||
struct PaintModeSettings paint_mode;
|
||||
|
||||
/* Particle Editing */
|
||||
struct ParticleEditSettings particle;
|
||||
|
||||
@@ -2278,11 +2294,21 @@ typedef enum eSculptFlags {
|
||||
SCULPT_HIDE_FACE_SETS = (1 << 17),
|
||||
} eSculptFlags;
|
||||
|
||||
/** PaintModeSettings.mode */
|
||||
typedef enum ePaintCanvasSource {
|
||||
/** Paint on the active node of the active material slot. */
|
||||
PAINT_CANVAS_SOURCE_MATERIAL = 0,
|
||||
/** Paint on a selected image. */
|
||||
PAINT_CANVAS_SOURCE_IMAGE = 1,
|
||||
/** Paint on the active color attribute (vertex color) layer. */
|
||||
PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE = 2,
|
||||
} ePaintCanvasSource;
|
||||
|
||||
/** #ImagePaintSettings.mode */
|
||||
typedef enum eImagePaintMode {
|
||||
IMAGEPAINT_MODE_MATERIAL = 0, /* detect texture paint slots from the material */
|
||||
IMAGEPAINT_MODE_IMAGE = 1, /* select texture paint image directly */
|
||||
} eImagePaintMode;
|
||||
/* Defines to let old texture painting use the new enum. */
|
||||
/* TODO(jbakker): rename usages. */
|
||||
#define IMAGEPAINT_MODE_MATERIAL PAINT_CANVAS_SOURCE_MATERIAL
|
||||
#define IMAGEPAINT_MODE_IMAGE PAINT_CANVAS_SOURCE_IMAGE
|
||||
|
||||
/** #ImagePaintSettings.interp */
|
||||
enum {
|
||||
|
@@ -8,10 +8,13 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
@@ -136,10 +139,9 @@ static void rna_Material_texpaint_begin(CollectionPropertyIterator *iter, Pointe
|
||||
iter, (void *)ma->texpaintslot, sizeof(TexPaintSlot), ma->tot_slots, 0, NULL);
|
||||
}
|
||||
|
||||
static void rna_Material_active_paint_texture_index_update(Main *bmain,
|
||||
Scene *UNUSED(scene),
|
||||
PointerRNA *ptr)
|
||||
static void rna_Material_active_paint_texture_index_update(bContext *C, PointerRNA *ptr)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
bScreen *screen;
|
||||
Material *ma = (Material *)ptr->owner_id;
|
||||
|
||||
@@ -152,26 +154,43 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain,
|
||||
}
|
||||
|
||||
if (ma->texpaintslot) {
|
||||
Image *image = ma->texpaintslot[ma->paint_active_slot].ima;
|
||||
for (screen = bmain->screens.first; screen; screen = screen->id.next) {
|
||||
wmWindow *win = ED_screen_window_find(screen, bmain->wm.first);
|
||||
if (win == NULL) {
|
||||
continue;
|
||||
}
|
||||
TexPaintSlot *slot = &ma->texpaintslot[ma->paint_active_slot];
|
||||
Image *image = slot->ima;
|
||||
if (image) {
|
||||
for (screen = bmain->screens.first; screen; screen = screen->id.next) {
|
||||
wmWindow *win = ED_screen_window_find(screen, bmain->wm.first);
|
||||
if (win == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ScrArea *area;
|
||||
for (area = screen->areabase.first; area; area = area->next) {
|
||||
SpaceLink *sl;
|
||||
for (sl = area->spacedata.first; sl; sl = sl->next) {
|
||||
if (sl->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = (SpaceImage *)sl;
|
||||
if (!sima->pin) {
|
||||
ED_space_image_set(bmain, sima, image, true);
|
||||
ScrArea *area;
|
||||
for (area = screen->areabase.first; area; area = area->next) {
|
||||
SpaceLink *sl;
|
||||
for (sl = area->spacedata.first; sl; sl = sl->next) {
|
||||
if (sl->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = (SpaceImage *)sl;
|
||||
if (!sima->pin) {
|
||||
ED_space_image_set(bmain, sima, image, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For compatibility reasons with vertex paint we activate the color attribute. */
|
||||
if (slot->attribute_name) {
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
if (ob != NULL && ob->type == OB_MESH) {
|
||||
Mesh *mesh = ob->data;
|
||||
CustomDataLayer *layer = BKE_id_attributes_color_find(&mesh->id, slot->attribute_name);
|
||||
if (layer != NULL) {
|
||||
BKE_id_attributes_active_color_set(&mesh->id, layer);
|
||||
}
|
||||
DEG_id_tag_update(&ob->id, 0);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEG_id_tag_update(&ma->id, 0);
|
||||
@@ -281,6 +300,49 @@ static void rna_TexPaintSlot_uv_layer_set(PointerRNA *ptr, const char *value)
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_TexPaintSlot_name_get(PointerRNA *ptr, char *value)
|
||||
{
|
||||
TexPaintSlot *data = (TexPaintSlot *)(ptr->data);
|
||||
|
||||
if (data->ima != NULL) {
|
||||
BLI_strncpy_utf8(value, data->ima->id.name + 2, MAX_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->attribute_name != NULL) {
|
||||
BLI_strncpy_utf8(value, data->attribute_name, MAX_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
value[0] = '\0';
|
||||
}
|
||||
|
||||
static int rna_TexPaintSlot_name_length(PointerRNA *ptr)
|
||||
{
|
||||
TexPaintSlot *data = (TexPaintSlot *)(ptr->data);
|
||||
if (data->ima != NULL) {
|
||||
return strlen(data->ima->id.name) - 2;
|
||||
}
|
||||
if (data->attribute_name != NULL) {
|
||||
return strlen(data->attribute_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rna_TexPaintSlot_icon_get(PointerRNA *ptr)
|
||||
{
|
||||
TexPaintSlot *data = (TexPaintSlot *)(ptr->data);
|
||||
if (data->ima != NULL) {
|
||||
return ICON_IMAGE;
|
||||
}
|
||||
if (data->attribute_name != NULL) {
|
||||
return ICON_COLOR;
|
||||
}
|
||||
|
||||
return ICON_NONE;
|
||||
}
|
||||
|
||||
static bool rna_is_grease_pencil_get(PointerRNA *ptr)
|
||||
{
|
||||
Material *ma = (Material *)ptr->data;
|
||||
@@ -963,6 +1025,17 @@ static void rna_def_tex_slot(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(
|
||||
srna, "Texture Paint Slot", "Slot that contains information about texture painting");
|
||||
|
||||
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_string_funcs(
|
||||
prop, "rna_TexPaintSlot_name_get", "rna_TexPaintSlot_name_length", NULL);
|
||||
RNA_def_property_ui_text(prop, "Name", "Name of the slot");
|
||||
|
||||
prop = RNA_def_property(srna, "icon_value", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_int_funcs(prop, "rna_TexPaintSlot_icon_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Icon", "Paint slot icon");
|
||||
|
||||
prop = RNA_def_property(srna, "uv_layer", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_maxlength(prop, 64); /* else it uses the pointer size! */
|
||||
RNA_def_property_string_sdna(prop, NULL, "uvname");
|
||||
@@ -1019,6 +1092,7 @@ void rna_def_texpaint_slots(BlenderRNA *brna, StructRNA *srna)
|
||||
RNA_def_property_range(prop, 0, SHRT_MAX);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Active Paint Texture Index", "Index of active texture paint slot");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(
|
||||
prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_Material_active_paint_texture_index_update");
|
||||
|
||||
|
@@ -3049,6 +3049,10 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "imapaint");
|
||||
RNA_def_property_ui_text(prop, "Image Paint", "");
|
||||
|
||||
prop = RNA_def_property(srna, "paint_mode", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "paint_mode");
|
||||
RNA_def_property_ui_text(prop, "Paint Mode", "");
|
||||
|
||||
prop = RNA_def_property(srna, "uv_sculpt", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "uvsculpt");
|
||||
RNA_def_property_ui_text(prop, "UV Sculpt", "");
|
||||
|
@@ -84,6 +84,13 @@ static const EnumPropertyItem rna_enum_gpencil_paint_mode[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static const EnumPropertyItem rna_enum_canvas_source_items[] = {
|
||||
{PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE, "COLOR_ATTRIBUTE", 0, "Color Attribute", ""},
|
||||
{PAINT_CANVAS_SOURCE_MATERIAL, "MATERIAL", 0, "Material", ""},
|
||||
{PAINT_CANVAS_SOURCE_IMAGE, "IMAGE", 0, "Image", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
const EnumPropertyItem rna_enum_symmetrize_direction_items[] = {
|
||||
{BMO_SYMMETRIZE_NEGATIVE_X, "NEGATIVE_X", 0, "-X to +X", ""},
|
||||
{BMO_SYMMETRIZE_POSITIVE_X, "POSITIVE_X", 0, "+X to -X", ""},
|
||||
@@ -418,6 +425,11 @@ static char *rna_ImagePaintSettings_path(PointerRNA *UNUSED(ptr))
|
||||
return BLI_strdup("tool_settings.image_paint");
|
||||
}
|
||||
|
||||
static char *rna_PaintModeSettings_path(PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
return BLI_strdup("tool_settings.paint_mode");
|
||||
}
|
||||
|
||||
static char *rna_UvSculpt_path(PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
return BLI_strdup("tool_settings.uv_sculpt");
|
||||
@@ -537,6 +549,30 @@ static void rna_ImaPaint_canvas_update(bContext *C, PointerRNA *UNUSED(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/** \name Paint mode settings
|
||||
* \{ */
|
||||
|
||||
static bool rna_PaintModeSettings_canvas_image_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
|
||||
{
|
||||
Image *image = (Image *)value.owner_id;
|
||||
return !ELEM(image->type, IMA_TYPE_COMPOSITE, IMA_TYPE_R_RESULT);
|
||||
}
|
||||
|
||||
static void rna_PaintModeSettings_canvas_source_update(bContext *C, PointerRNA *UNUSED(ptr))
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
/* When canvas source changes the pbvh would require updates when switching between color
|
||||
* attributes. */
|
||||
if (ob && ob->type == OB_MESH) {
|
||||
BKE_texpaint_slots_refresh_object(scene, ob);
|
||||
DEG_id_tag_update(&ob->id, 0);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, &ob->id);
|
||||
}
|
||||
}
|
||||
|
||||
/* \} */
|
||||
|
||||
static bool rna_ImaPaint_detect_data(ImagePaintSettings *imapaint)
|
||||
{
|
||||
return imapaint->missing_data == 0;
|
||||
@@ -964,6 +1000,29 @@ static void rna_def_vertex_paint(BlenderRNA *brna)
|
||||
prop, "Radial Symmetry Count X Axis", "Number of times to copy strokes across the surface");
|
||||
}
|
||||
|
||||
static void rna_def_paint_mode(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "PaintModeSettings", NULL);
|
||||
RNA_def_struct_sdna(srna, "PaintModeSettings");
|
||||
RNA_def_struct_path_func(srna, "rna_PaintModeSettings_path");
|
||||
RNA_def_struct_ui_text(srna, "Paint Mode", "Properties of paint mode");
|
||||
|
||||
prop = RNA_def_property(srna, "canvas_source", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_enum_canvas_source_items);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_ui_text(prop, "Source", "Source to select canvas from");
|
||||
RNA_def_property_update(prop, 0, "rna_PaintModeSettings_canvas_source_update");
|
||||
|
||||
prop = RNA_def_property(srna, "canvas_image", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, NULL, NULL, NULL, "rna_PaintModeSettings_canvas_image_poll");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_ui_text(prop, "Texture", "Image used as as painting target");
|
||||
}
|
||||
|
||||
static void rna_def_image_paint(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -1551,6 +1610,7 @@ void RNA_def_sculpt_paint(BlenderRNA *brna)
|
||||
rna_def_gp_sculptpaint(brna);
|
||||
rna_def_gp_weightpaint(brna);
|
||||
rna_def_vertex_paint(brna);
|
||||
rna_def_paint_mode(brna);
|
||||
rna_def_image_paint(brna);
|
||||
rna_def_particle_edit(brna);
|
||||
rna_def_gpencil_guides(brna);
|
||||
|
@@ -32,6 +32,7 @@
|
||||
# include "DNA_space_types.h"
|
||||
|
||||
# include "ED_asset.h"
|
||||
# include "ED_paint.h"
|
||||
|
||||
# include "RNA_access.h"
|
||||
|
||||
@@ -180,6 +181,12 @@ const EnumPropertyItem *rna_WorkSpace_tools_mode_itemf(bContext *UNUSED(C),
|
||||
return DummyRNA_DEFAULT_items;
|
||||
}
|
||||
|
||||
static bool rna_WorkSpaceTool_use_paint_canvas_get(PointerRNA *ptr)
|
||||
{
|
||||
bToolRef *tref = ptr->data;
|
||||
return ED_paint_tool_use_canvas(NULL, tref);
|
||||
}
|
||||
|
||||
static int rna_WorkSpaceTool_index_get(PointerRNA *ptr)
|
||||
{
|
||||
bToolRef *tref = ptr->data;
|
||||
@@ -291,6 +298,12 @@ static void rna_def_workspace_tool(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Tool Mode", "");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "use_paint_canvas", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Index", "");
|
||||
RNA_def_property_boolean_funcs(prop, "rna_WorkSpaceTool_use_paint_canvas_get", NULL);
|
||||
RNA_def_property_ui_text(prop, "Use Paint Canvas", "Does this tool use an painting canvas");
|
||||
|
||||
RNA_define_verify_sdna(0);
|
||||
prop = RNA_def_property(srna, "has_datablock", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
@@ -162,8 +162,21 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode
|
||||
}
|
||||
}
|
||||
|
||||
bNode *nodeGetActiveTexture(bNodeTree *ntree)
|
||||
bool nodeSupportsActiveFlag(const bNode *node, int sub_activity)
|
||||
{
|
||||
BLI_assert(ELEM(sub_activity, NODE_ACTIVE_TEXTURE, NODE_ACTIVE_PAINT_CANVAS));
|
||||
switch (sub_activity) {
|
||||
case NODE_ACTIVE_TEXTURE:
|
||||
return node->typeinfo->nclass == NODE_CLASS_TEXTURE;
|
||||
case NODE_ACTIVE_PAINT_CANVAS:
|
||||
return ELEM(node->type, SH_NODE_TEX_IMAGE, SH_NODE_ATTRIBUTE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bNode *node_get_active(bNodeTree *ntree, int sub_activity)
|
||||
{
|
||||
BLI_assert(ELEM(sub_activity, NODE_ACTIVE_TEXTURE, NODE_ACTIVE_PAINT_CANVAS));
|
||||
/* this is the node we texture paint and draw in textured draw */
|
||||
bNode *inactivenode = nullptr, *activetexnode = nullptr, *activegroup = nullptr;
|
||||
bool hasgroup = false;
|
||||
@@ -173,14 +186,14 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree)
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->flag & NODE_ACTIVE_TEXTURE) {
|
||||
if (node->flag & sub_activity) {
|
||||
activetexnode = node;
|
||||
/* if active we can return immediately */
|
||||
if (node->flag & NODE_ACTIVE) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
else if (!inactivenode && node->typeinfo->nclass == NODE_CLASS_TEXTURE) {
|
||||
else if (!inactivenode && nodeSupportsActiveFlag(node, sub_activity)) {
|
||||
inactivenode = node;
|
||||
}
|
||||
else if (node->type == NODE_GROUP) {
|
||||
@@ -195,7 +208,7 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree)
|
||||
|
||||
/* first, check active group for textures */
|
||||
if (activegroup) {
|
||||
bNode *tnode = nodeGetActiveTexture((bNodeTree *)activegroup->id);
|
||||
bNode *tnode = node_get_active((bNodeTree *)activegroup->id, sub_activity);
|
||||
/* active node takes priority, so ignore any other possible nodes here */
|
||||
if (tnode) {
|
||||
return tnode;
|
||||
@@ -210,8 +223,8 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree)
|
||||
/* node active texture node in this tree, look inside groups */
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == NODE_GROUP) {
|
||||
bNode *tnode = nodeGetActiveTexture((bNodeTree *)node->id);
|
||||
if (tnode && ((tnode->flag & NODE_ACTIVE_TEXTURE) || !inactivenode)) {
|
||||
bNode *tnode = node_get_active((bNodeTree *)node->id, sub_activity);
|
||||
if (tnode && ((tnode->flag & sub_activity) || !inactivenode)) {
|
||||
return tnode;
|
||||
}
|
||||
}
|
||||
@@ -221,6 +234,16 @@ bNode *nodeGetActiveTexture(bNodeTree *ntree)
|
||||
return inactivenode;
|
||||
}
|
||||
|
||||
bNode *nodeGetActiveTexture(bNodeTree *ntree)
|
||||
{
|
||||
return node_get_active(ntree, NODE_ACTIVE_TEXTURE);
|
||||
}
|
||||
|
||||
bNode *nodeGetActivePaintCanvas(bNodeTree *ntree)
|
||||
{
|
||||
return node_get_active(ntree, NODE_ACTIVE_PAINT_CANVAS);
|
||||
}
|
||||
|
||||
void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, bNode *output_node)
|
||||
{
|
||||
bNodeExec *nodeexec;
|
||||
|
Reference in New Issue
Block a user