Sculpt-dev: fix brush input mapping inheritance

* Brush input mappings now have three
  inheritance mode: "always", "never" and
  "channel" (use channel's inheritance mode).
* Note that the UI exposes a single inherit icon,
  which just toggles between "always" and
  "never," to lessen user confusion.
* Brush mappings default to "never" inheritance
  mode.
* Fixed wrong node update flag in bke_pbvh_insert_face_finalize
  leading to disappearing parts of the mesh.
This commit is contained in:
Joseph Eagar 2021-11-16 13:26:39 -08:00
parent b43119ad84
commit cddcc54f32
17 changed files with 346 additions and 120 deletions

View File

@ -116,14 +116,24 @@ def object_child_map(objects):
return objects_children
import sys
def get_active_vcol(me):
vcol = me.vertex_colors.active
if not vcol and len(me.vertex_colors) > 0:
vcol = me.vertex_colors[0]
return vcol
def mesh_data_lists_from_mesh(me, material_colors):
me_loops = me.loops[:]
me_loops_color = me.vertex_colors.active.data[:]
me_loops_color = get_active_vcol(me)
me_loops_color = me_loops_color.data[:] if me_loops_color else None
me_verts = me.vertices[:]
me_polys = me.polygons[:]
tris_data = []
white = [1, 1, 1, 1]
for p in me_polys:
# Note, all faces are handled, backfacing/zero area is checked just before writing.
material_index = p.material_index
@ -135,22 +145,25 @@ def mesh_data_lists_from_mesh(me, material_colors):
l_sta = p.loop_start
l_len = p.loop_total
loops_poly = me_loops[l_sta:l_sta + l_len]
color_poly = me_loops_color[l_sta:l_sta + l_len]
color_poly = me_loops_color[l_sta:l_sta + l_len] if me_loops_color else None
i0 = 0
i1 = 1
# we only write tris now
assert(len(loops_poly) == 3)
for i2 in range(2, l_len):
l0 = loops_poly[i0]
l1 = loops_poly[i1]
l2 = loops_poly[i2]
c0 = color_poly[i0]
c1 = color_poly[i1]
c2 = color_poly[i2]
if color_poly:
c0 = color_poly[i0]
c1 = color_poly[i1]
c2 = color_poly[i2]
else:
c1 = c2 = c3 = white
v0 = me_verts[l0.vertex_index]
v1 = me_verts[l1.vertex_index]
v2 = me_verts[l2.vertex_index]

View File

@ -6298,13 +6298,11 @@ def km_3d_view_tool_sculpt_cloth_filter(params):
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [("sculpt.cloth_filter", params.tool_maybe_tweak_event, None)]},)
def km_3d_view_tool_sculpt_color_filter(params):
return ("3D View Tool: Sculpt, Color Filter",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [("sculpt.color_filter", params.tool_maybe_tweak_event, None)]},)
def km_3d_view_tool_sculpt_mask_by_color(params):
return ("3D View Tool: Sculpt, Mask by Color",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},

View File

@ -494,14 +494,20 @@ class UnifiedPaintPanel:
sd.channels.ensure(ch)
finalch = sd.channels[prop_name]
if ch.mappings["PRESSURE"].inherit:
pressurech = finalch
is_toolset = True
path = "tool_settings.sculpt.channels[\"%s\"]" % ch.idname
else:
path = "tool_settings.sculpt.brush.channels[\"%s\"]" % ch.idname
if not (ch.inherit and ch.mappings["PRESSURE"].inherit_mode == "NEVER"):
pressurech = finalch
if pressurech == ch and ch.mappings["PRESSURE"].inherit_mode == "ALWAYS":
sd = context.tool_settings.sculpt
sd.channels.ensure(ch)
pressurech = sd.channels[ch.idname]
if show_reorder:
props = row.operator("brush.change_channel_order", text="", icon="TRIA_UP")
props.channel = ch.idname
@ -609,9 +615,15 @@ class UnifiedPaintPanel:
for i, mp in enumerate(ch.mappings):
mp0 = mp
if mp.inherit:
if mp.inherit_mode != "NEVER":
mp = finalch.mappings[i]
if mp.inherit_mode == "ALWAYS" and finalch == ch:
sd = context.tool_settings.sculpt
sd.channels.ensure(ch)
mp = sd.channels[ch.idname].mappings[i]
row2 = layout.row(align=True)
row2.use_property_split = False
row2.use_property_decorate = False
@ -626,7 +638,14 @@ class UnifiedPaintPanel:
row2.prop(mp0, "ui_expanded", text="", emboss=False, icon="DOWNARROW_HLT" if mp.ui_expanded else "RIGHTARROW")
row2.label(text=name)
#row3 = row2.row(align=True)
#row3.prop_enum(mp0, "inherit_mode", "ALWAYS", icon="BRUSHES_ALL", text="")
#row3.prop_enum(mp0, "inherit_mode", "NEVER", icon="FORWARD", text="")
#row3.prop_enum(mp0, "inherit_mode", "USE_CHANNEL", icon="FORWARD", text="")
row2.prop(mp0, "inherit", text="", icon="BRUSHES_ALL")
row2.prop(mp, "enabled", text="", icon="STYLUS_PRESSURE")
row2.prop(mp, "invert", text="", icon="ARROW_LEFTRIGHT")
@ -643,7 +662,7 @@ class UnifiedPaintPanel:
row = col.row(align=True)
if mp0.inherit or toolsettings_only:
if mp0.inherit_mode == "ALWAYS" or (mp0.inherit_mode == "USE_CHANNEL" and ch.inherits):
path2 = path + ".mappings[\"%s\"].curve" % (mp.type)
else:
brushpath = "tool_settings.sculpt.brush.channels[\"%s\"]" % ch.idname

View File

@ -1161,9 +1161,15 @@ class _defs_sculpt:
@staticmethod
def generate_from_brushes(context):
exclude_filter = {}
# Use 'bpy.context' instead of 'context' since it can be None.
prefs = bpy.context.preferences
# don't hide this behind experimental option in sculpt branch?
# joeedh
#if not prefs.experimental.use_sculpt_uvsmooth:
# exclude_filter["UV_SMOOTH"] = True
return generate_from_enum_ex(context,
idname_prefix="builtin_brush.",
icon_prefix="brush.sculpt.",
@ -1396,6 +1402,7 @@ class _defs_sculpt:
def color_filter():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sculpt.color_filter")
layout.prop(props, "type", expand=False)
if props.type == 'FILL':
layout.prop(props, "fill_color", expand=False)
@ -2587,13 +2594,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_sculpt.mesh_filter,
_defs_sculpt.cloth_filter,
_defs_sculpt.ipmask_filter,
lambda context: ((_defs_sculpt.color_filter,)
if context is None
else ()),
None,
lambda context: ((_defs_sculpt.mask_by_color,)
if context is None
else ()),
_defs_sculpt.color_filter,
_defs_sculpt.mask_by_color,
None,
_defs_sculpt.face_set_edit,
None,

View File

@ -290,8 +290,22 @@ class _draw_tool_settings_context_mode:
text, row.ui_units_x = name_size_overrides[ch.idname]
row.prop(final_ch, "value", slider=True, expand=False, text=text)
if final_ch.type in ["FLOAT", "INT"]:
row.prop(final_ch.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
sd = context.tool_settings.sculpt
sd.channels.ensure(ch)
if ch.mappings["PRESSURE"].inherit_mode != "NEVER":
pressurech = final_ch
if final_ch == ch and ch.mappings["PRESSURE"].inherit_mode == "ALWAYS":
sd = context.tool_settings.sculpt
sd.channels.ensure(ch)
pressurech = sd.channels[ch.idname]
else:
pressurech = ch
if ch.type in ["FLOAT", "INT"]:
row.prop(pressurech.mappings["PRESSURE"], "enabled", text="", icon="STYLUS_PRESSURE")
#UnifiedPaintPanel.channel_unified(row, context, brush,
#ch.idname, header=True)

View File

@ -1143,13 +1143,13 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
col2 = col.row() # sub.column()
ch = UnifiedPaintPanel.get_channel(context, brush, "dyntopo_mode")
col2.use_property_split = False
col2.use_property_split = True
row2 = col2.row()
row2.prop_enum(ch, "flags_value", "CLEANUP", icon="CHECKBOX_HLT" if "CLEANUP" in ch.flags_value else "CHECKBOX_DEHLT")
row2.prop_enum(ch, "flags_value", "CLEANUP")
row3 = row2.row()
row3.enabled = "COLLAPSE" not in ch.flags_value
row3.prop_enum(ch, "flags_value", "LOCAL_COLLAPSE", icon="CHECKBOX_HLT" if "LOCAL_COLLAPSE" in ch.flags_value else "CHECKBOX_DEHLT")
row3.prop_enum(ch, "flags_value", "LOCAL_COLLAPSE")
"""
UnifiedPaintPanel.channel_unified(
@ -1380,8 +1380,8 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
layout.separator()
layout.prop(sculpt, "symmetrize_direction")
layout.operator("sculpt.symmetrize")
layout.prop(WindowManager.operator_properties_last("sculpt.symmetrize"), "merge_tolerance")
layout.operator("sculpt.symmetrize")
class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):

View File

@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 1
#define BLENDER_FILE_SUBVERSION 2
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -243,6 +243,8 @@ BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const
void BKE_brush_mapping_reset(BrushChannel *ch, int tool, int mapping);
void BKE_brush_mapping_inherit_all(BrushChannel *ch);
void BKE_brush_channelset_inherit_mappings(BrushChannelSet *chset);
void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent);
@ -305,7 +307,8 @@ void BKE_brush_channel_curve_assign(BrushChannel *ch, BrushCurve *curve);
/* returns size of vector */
int BKE_brush_channel_get_vector(BrushChannel *ch, float out[4], BrushMappingData *mapdata);
float BKE_brush_channelset_get_final_vector(BrushChannelSet *brushset,
/* returns size of vector */
int BKE_brush_channelset_get_final_vector(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
float r_vec[4],

View File

@ -102,6 +102,18 @@ struct CurveMappingCache *brush_curve_cache = NULL;
extern BrushChannelType brush_builtin_channels[];
extern int brush_builtin_channel_len;
static bool brush_mapping_inherits(BrushChannel *ch, BrushMapping *mp)
{
switch (mp->inherit_mode) {
case BRUSH_MAPPING_INHERIT_NEVER:
return false;
case BRUSH_MAPPING_INHERIT_ALWAYS:
return true;
case BRUSH_MAPPING_INHERIT_CHANNEL:
return ch->flag & BRUSH_CHANNEL_INHERIT;
}
}
void BKE_brush_channel_system_init()
{
brush_curve_cache = BKE_curvemapping_cache_create();
@ -449,7 +461,7 @@ void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
}
if (mdef->inherit) {
mp->flag |= BRUSH_MAPPING_INHERIT;
mp->flag |= BRUSH_MAPPING_INHERIT_ALWAYS;
}
int slope = CURVEMAP_SLOPE_POSITIVE;
@ -831,9 +843,12 @@ void BKE_brush_channelset_merge(BrushChannelSet *dst,
of BRUSH_MAPPING_FLAG doen't prevent mapping inheritance
if BRUSH_CHANNEL_INHERIT in ch->flag *is* set.*/
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
if (ch->mappings[i].flag & BRUSH_MAPPING_INHERIT) {
if (brush_mapping_inherits(ch, ch->mappings + i)) {
BKE_brush_mapping_copy_data(mch->mappings + i, pch->mappings + i);
}
else {
BKE_brush_mapping_copy_data(mch->mappings + i, ch->mappings + i);
}
}
if (ch->flag & BRUSH_CHANNEL_INHERIT) {
@ -1081,27 +1096,60 @@ void BKE_brush_channel_set_int(BrushChannel *ch, int val)
ch->ivalue = val;
}
void brush_channel_apply_mapping_flags(BrushChannel *ch, BrushChannel *child, BrushChannel *parent)
{
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
BrushMapping *mp = ch->mappings + i;
BrushMapping *cmp = child ? child->mappings + i : NULL;
BrushMapping *pmp = parent ? parent->mappings + i : NULL;
if (pmp && brush_mapping_inherits(child, cmp)) {
*mp = *pmp;
}
else {
*mp = *cmp;
}
}
}
static BrushChannel *brush_channel_final(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
BrushChannel **r_child,
BrushChannel **r_parent)
{
if (!parent) {
*r_parent = NULL;
*r_child = BKE_brush_channelset_lookup(child, idname);
return *r_child;
}
BrushChannel *ch = BKE_brush_channelset_lookup(child, idname);
*r_child = ch;
*r_parent = BKE_brush_channelset_lookup(parent, idname);
if (!ch || (ch->flag & BRUSH_CHANNEL_INHERIT)) {
return *r_parent;
}
return ch;
}
int BKE_brush_channelset_get_final_int(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
BrushMappingData *mapdata)
{
if (!parent) {
return BKE_brush_channelset_get_int(child, idname, mapdata);
}
BrushChannel *ch = BKE_brush_channelset_lookup(child, idname);
if (!ch || (ch->flag & BRUSH_CHANNEL_INHERIT)) {
BrushChannel *pch = BKE_brush_channelset_lookup(parent, idname);
if (pch) {
return BKE_brush_channel_get_int(pch, mapdata);
}
}
BrushChannel *parentch, *childch;
BrushChannel *ch = brush_channel_final(child, parent, idname, &childch, &parentch);
if (ch) {
return BKE_brush_channel_get_int(ch, mapdata);
BrushChannel cpy = *ch;
brush_channel_apply_mapping_flags(&cpy, childch, parentch);
return BKE_brush_channel_get_int(&cpy, mapdata);
}
printf("%s: failed to find brush channel %s\n", __func__, idname);
@ -1137,23 +1185,19 @@ void BKE_brush_channelset_set_final_int(BrushChannelSet *child,
BKE_brush_channel_set_int(ch, value);
}
float BKE_brush_channelset_get_final_float(BrushChannelSet *brushset,
BrushChannelSet *toolset,
float BKE_brush_channelset_get_final_float(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
BrushMappingData *mapdata)
{
BrushChannel *ch = BKE_brush_channelset_lookup(brushset, idname);
if (!ch || (ch->flag & BRUSH_CHANNEL_INHERIT)) {
BrushChannel *pch = BKE_brush_channelset_lookup(toolset, idname);
if (pch) {
return BKE_brush_channel_get_float(pch, mapdata);
}
}
BrushChannel *parentch, *childch;
BrushChannel *ch = brush_channel_final(child, parent, idname, &childch, &parentch);
if (ch) {
return BKE_brush_channel_get_float(ch, mapdata);
BrushChannel cpy = *ch;
brush_channel_apply_mapping_flags(&cpy, childch, parentch);
return BKE_brush_channel_get_float(&cpy, mapdata);
}
printf("%s: failed to find brush channel %s\n", __func__, idname);
@ -1240,29 +1284,26 @@ int BKE_brush_channel_get_vector(BrushChannel *ch, float out[4], BrushMappingDat
return size;
}
float BKE_brush_channelset_get_final_vector(BrushChannelSet *brushset,
BrushChannelSet *toolset,
const char *idname,
float r_vec[4],
BrushMappingData *mapdata)
int BKE_brush_channelset_get_final_vector(BrushChannelSet *child,
BrushChannelSet *parent,
const char *idname,
float r_vec[4],
BrushMappingData *mapdata)
{
BrushChannel *ch = BKE_brush_channelset_lookup(brushset, idname);
if (!ch || (ch->flag & BRUSH_CHANNEL_INHERIT)) {
BrushChannel *pch = BKE_brush_channelset_lookup(toolset, idname);
if (pch) {
return BKE_brush_channel_get_vector(pch, r_vec, mapdata);
}
}
BrushChannel *parentch, *childch;
BrushChannel *ch = brush_channel_final(child, parent, idname, &childch, &parentch);
if (ch) {
return BKE_brush_channel_get_vector(ch, r_vec, mapdata);
BrushChannel cpy = *ch;
brush_channel_apply_mapping_flags(&cpy, childch, parentch);
return BKE_brush_channel_get_vector(&cpy, r_vec, mapdata);
}
printf("%s: failed to find brush channel %s\n", __func__, idname);
return 0.0f;
zero_v4(r_vec);
return 0;
}
void BKE_brush_channelset_set_final_vector(BrushChannelSet *brushset,
@ -1521,18 +1562,6 @@ static void _int_set_uninherit(BrushChannelSet *chset, const char *channel, int
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
}
/*flag all mappings to use inherited curves even if owning channel
is not set to inherit.*/
void BKE_brush_commandset_inherit_all_mappings(BrushChannelSet *chset)
{
BrushChannel *ch;
for (ch = chset->channels.first; ch; ch = ch->next) {
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
ch->mappings[i].flag |= BRUSH_MAPPING_INHERIT;
}
}
}
static void commandlist_add_auto_fset(BrushChannelSet *chset,
BrushCommandList *cl,
Brush *brush,
@ -1591,7 +1620,7 @@ static void commandlist_add_dyntopo(BrushChannelSet *chset,
float_set_uninherit(cmd->params, spacing, spacing);
float_set_uninherit(cmd->params, radius, radius2);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
}
}
static void bke_builtin_commandlist_create_paint(Brush *brush,
@ -1604,7 +1633,7 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
cmd = BKE_brush_commandlist_add(cl, chset, true);
BKE_brush_command_init(cmd, tool);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
float radius = BRUSHSET_GET_FLOAT(chset, radius, NULL);
@ -1648,7 +1677,7 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
float_set_uninherit(cmd->params, projection, autosmooth_projection);
float_set_uninherit(cmd->params, spacing, autosmooth_spacing);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
}
float vcol_boundary = BKE_brush_channelset_get_float(chset, "vcol_boundary_factor", NULL);
@ -1662,7 +1691,7 @@ static void bke_builtin_commandlist_create_paint(Brush *brush,
float_set_uninherit(cmd->params, spacing, GETF("vcol_boundary_spacing"));
float_set_uninherit(cmd->params, strength, vcol_boundary);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
}
#undef GETF
@ -1725,7 +1754,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
cmd = BKE_brush_commandlist_add(cl, chset, true);
BKE_brush_command_init(cmd, tool);
BKE_builtin_apply_hard_edge_mode(cmd->params, hard_edge_mode);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
bool no_autosmooth = ELEM(tool, SCULPT_TOOL_BOUNDARY, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK);
bool no_rake = ELEM(tool, SCULPT_TOOL_BOUNDARY, SCULPT_TOOL_MASK);
@ -1765,7 +1794,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
cmd = BKE_brush_command_init(BKE_brush_commandlist_add(cl, chset, true), smooth_tool);
BKE_builtin_apply_hard_edge_mode(cmd->params, hard_edge_mode);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
BrushChannel *ch = BRUSHSET_ENSURE_BUILTIN(cmd->params, falloff_curve);
BrushChannel *ch2 = BRUSHSET_LOOKUP(chset, autosmooth_falloff_curve);
@ -1831,7 +1860,7 @@ void BKE_builtin_commandlist_create(Brush *brush,
float_set_uninherit(cmd->params, projection, topology_rake_projection);
float_set_uninherit(cmd->params, spacing, topology_rake_spacing);
BKE_brush_commandset_inherit_all_mappings(cmd->params);
BKE_brush_channelset_inherit_mappings(cmd->params);
}
}
@ -2070,10 +2099,17 @@ void BKE_brush_channel_category_set(BrushChannel *ch, const char *str)
ch->category = BLI_strdup(str);
}
void BKE_brush_channelset_inherit_mappings(BrushChannelSet *chset)
{
for (BrushChannel *ch = chset->channels.first; ch; ch = ch->next) {
BKE_brush_mapping_inherit_all(ch);
}
}
void BKE_brush_mapping_inherit_all(BrushChannel *ch)
{
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
ch->mappings[i].flag |= BRUSH_MAPPING_INHERIT;
ch->mappings[i].inherit_mode = BRUSH_MAPPING_INHERIT_ALWAYS;
}
}

View File

@ -1113,7 +1113,9 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(smooth_strength_factor)->flag |= BRUSH_CHANNEL_INHERIT;
}
ADDCH(smooth_strength_projection);
if (!BRUSHSET_LOOKUP(chset, smooth_strength_projection)) {
ADDCH(smooth_strength_projection)->flag |= BRUSH_CHANNEL_INHERIT;
}
ADDCH(accumulate);
ADDCH(original_normal);
@ -1712,7 +1714,6 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
BRUSHSET_SET_FLOAT(chset, hardness, 0.4f);
BRUSHSET_SET_FLOAT(chset, spacing, 10.0f);
BRUSHSET_SET_FLOAT(chset, strength, 0.6f);
BRUSHSET_LOOKUP(chset, strength)->flag &= ~BRUSH_MAPPING_INHERIT;
BrushChannel *ch = BRUSHSET_LOOKUP(chset, hue_offset);
BKE_brush_mapping_reset(ch, SCULPT_TOOL_PAINT, BRUSH_MAPPING_PRESSURE);
@ -1923,8 +1924,7 @@ void BKE_brush_channelset_check_radius(BrushChannelSet *chset)
ch2->flag |= mask & ch1->flag;
}
mask = BRUSH_MAPPING_ENABLED | BRUSH_MAPPING_INHERIT | BRUSH_MAPPING_INVERT |
BRUSH_MAPPING_UI_EXPANDED;
mask = BRUSH_MAPPING_ENABLED | BRUSH_MAPPING_INVERT | BRUSH_MAPPING_UI_EXPANDED;
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
BrushMapping *mp1 = ch1->mappings + i;

View File

@ -3183,6 +3183,14 @@ void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg)
PBVHNode **nodes;
int totnode;
if (pbvh->type == PBVH_BMESH) {
for (int i = 0; i < pbvh->totnode; i++) {
if (pbvh->nodes[i].flag & PBVH_Leaf) {
BKE_pbvh_bmesh_check_tris(pbvh, pbvh->nodes + i);
}
}
}
BKE_pbvh_search_gather(
pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);

View File

@ -614,7 +614,7 @@ void bke_pbvh_insert_face_finalize(PBVH *pbvh, BMFace *f, const int ni)
int updateflag = PBVH_UpdateTris | PBVH_UpdateBB | PBVH_UpdateDrawBuffers |
PBVH_UpdateCurvatureDir | PBVH_UpdateOtherVerts;
updateflag |= PBVH_UpdateColor | PBVH_UpdateMask | PBVH_UpdateNormals | PBVH_UpdateOriginalBB;
updateflag |= PBVH_UpdateVisibility | PBVH_UpdateRedraw;
updateflag |= PBVH_UpdateVisibility | PBVH_UpdateRedraw | PBVH_RebuildDrawBuffers;
node->flag |= updateflag;
@ -1286,6 +1286,8 @@ void pbvh_bmesh_normals_update(PBVH *pbvh, PBVHNode **nodes, int totnode)
datas[i].cd_sculpt_vert = pbvh->cd_sculpt_vert;
datas[i].cd_vert_node_offset = pbvh->cd_vert_node_offset;
datas[i].node_nr = nodes[i] - pbvh->nodes;
BKE_pbvh_bmesh_check_tris(pbvh, nodes[i]);
}
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@ -2317,6 +2319,13 @@ void BKE_pbvh_build_bmesh(PBVH *pbvh,
pbvh_bmesh_create_nodes_fast_recursive_create(pbvh, nodeinfo, bbc_array, &rootnode);
if (!totleaf) {
leaves = MEM_mallocN(sizeof(void*), "leaves");
totleaf = 1;
leaves[0] = &rootnode;
}
/* build leaf nodes */
LeafBuilderThreadData tdata = {
.pbvh = pbvh, .nodeinfo = nodeinfo, .bbc_array = bbc_array, .leaves = leaves};
@ -2777,7 +2786,7 @@ bool BKE_pbvh_bmesh_check_tris(PBVH *pbvh, PBVHNode *node)
BLI_array_staticdeclare(loops, 128);
BLI_array_staticdeclare(loops_idx, 128);
PBVHTriBuf *tribufs = NULL; // material-specific tribuffers
PBVHTriBuf *tribufs = NULL; // material-specific tri buffers
BLI_array_declare(tribufs);
node->flag &= ~PBVH_UpdateTris;

View File

@ -2500,6 +2500,27 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
BKE_brush_channelset_free(chset);
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 301, 2)) {
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (!brush->channels) {
continue;
}
BrushChannelSet *chset = brush->channels;
BrushChannel *ch;
for (int i = 0; i < 2; i++) {
ch = i ? BRUSHSET_LOOKUP(chset, smooth_strength_projection) :
BRUSHSET_LOOKUP(chset, smooth_strength_factor);
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
ch->mappings[i].inherit_mode = BRUSH_MAPPING_INHERIT_ALWAYS;
}
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -830,6 +830,58 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
ops.mesh.loopcut_slide
ops.mesh.offset_edge_loops_slide
ops.mesh.polybuild_hover
ops.mesh.primitive_cone_add_gizmo
ops.mesh.primitive_cube_add_gizmo
ops.mesh.primitive_cylinder_add_gizmo
ops.mesh.primitive_grid_add_gizmo
ops.mesh.primitive_sphere_add_gizmo
ops.mesh.primitive_torus_add_gizmo
ops.mesh.rip
ops.mesh.rip_edge
ops.mesh.spin
ops.mesh.spin.duplicate
ops.mesh.vertices_smooth
ops.node.links_cut
ops.paint.eyedropper_add
ops.paint.vertex_color_fill
ops.paint.weight_fill
ops.paint.weight_gradient
ops.paint.weight_sample
ops.paint.weight_sample_group
ops.pose.breakdowner
ops.pose.push
ops.pose.relax
ops.sculpt.border_face_set
ops.sculpt.border_hide
ops.sculpt.border_mask
ops.sculpt.box_trim
ops.sculpt.cloth_filter
ops.sculpt.color_filter
ops.sculpt.face_set_edit
ops.sculpt.ipmask_filter
ops.sculpt.lasso_face_set
ops.sculpt.lasso_mask
ops.sculpt.lasso_trim
ops.sculpt.line_mask
ops.sculpt.line_project
ops.sculpt.mesh_filter
ops.sequencer.blade
ops.transform.bone_envelope
ops.transform.bone_size
ops.transform.edge_slide
ops.transform.push_pull
ops.transform.resize.cage
ops.transform.resize
ops.transform.rotate
ops.transform.shear
ops.transform.shrink_fatten
ops.transform.tilt
ops.transform.tosphere
ops.transform.transform
ops.transform.translate
ops.transform.vert_slide
ops.transform.vertex_random
ops.view3d.ruler
# END ICON_GEOM_NAMES
)

View File

@ -43,7 +43,7 @@ typedef struct BrushMapping {
float premultiply; // premultiply input data
int mapfunc;
float func_cutoff;
int _pad[1];
char inherit_mode, _pad[3];
} BrushMapping;
typedef struct BrushCurve {
@ -79,15 +79,24 @@ typedef struct BrushChannelSet {
#define BRUSH_CHANNEL_MAX_IDNAME sizeof(((BrushChannel){0}).idname)
// mapping flags
/* BrushMapping->flag */
enum {
BRUSH_MAPPING_ENABLED = 1 << 0,
BRUSH_MAPPING_INVERT = 1 << 1,
BRUSH_MAPPING_UI_EXPANDED = 1 << 2,
BRUSH_MAPPING_INHERIT = 1 << 3, // inherit mapping even if channel overall is not inherited
};
// BrushMapping->mapfunc
/* BrushMapping->inherit_mode */
enum {
/* never inherit */
BRUSH_MAPPING_INHERIT_NEVER,
/* always inherit */
BRUSH_MAPPING_INHERIT_ALWAYS,
/* use channel's inheritance mode */
BRUSH_MAPPING_INHERIT_CHANNEL
};
/* BrushMapping->mapfunc */
typedef enum {
BRUSH_MAPFUNC_NONE,
BRUSH_MAPFUNC_SAW,

View File

@ -418,6 +418,25 @@ PointerRNA rna_BrushCurve_curve_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, curve->curve);
}
bool rna_BrushMapping_inherit_get(PointerRNA *ptr)
{
BrushMapping *mp = (BrushMapping *)ptr->data;
return mp->inherit_mode;
}
void rna_BrushMapping_inherit_set(PointerRNA *ptr, bool val)
{
BrushMapping *mp = (BrushMapping *)ptr->data;
if (val) {
mp->inherit_mode = BRUSH_MAPPING_INHERIT_ALWAYS;
}
else {
mp->inherit_mode = BRUSH_MAPPING_INHERIT_NEVER;
}
}
int rna_BrushChannel_mappings_begin(CollectionPropertyIterator *iter, struct PointerRNA *ptr)
{
BrushChannel *ch = ptr->data;
@ -661,44 +680,67 @@ void RNA_def_brush_mapping(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Brush Mapping", "Brush Mapping");
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, "BrushMapping", "factor");
RNA_def_property_float_sdna(prop, NULL, "factor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Factor", "Mapping factor");
prop = RNA_def_property(srna, "premultiply", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, "BrushMapping", "premultiply");
RNA_def_property_float_sdna(prop, NULL, "premultiply");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -100, 100, 0.01, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Pre-Multiply", "Multiply input data by this amount");
prop = RNA_def_property(srna, "func_cutoff", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, "BrushMapping", "func_cutoff");
RNA_def_property_float_sdna(prop, NULL, "func_cutoff");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Cutoff", "Cutoff for square and cutoff modes");
prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, "BrushMapping", "min");
RNA_def_property_float_sdna(prop, NULL, "min");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.001, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Min", "");
prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, "BrushMapping", "max");
RNA_def_property_float_sdna(prop, NULL, "max");
RNA_def_property_range(prop, -100000, 100000);
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.001, 3);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Max", "");
prop = RNA_def_property(srna, "inherit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_INHERIT);
static EnumPropertyItem inherit_mode_items[] = {
{BRUSH_MAPPING_INHERIT_NEVER,
"NEVER",
ICON_NONE,
"Never",
"Do not inherit from scene defaults even if channel is set to inherit"},
{BRUSH_MAPPING_INHERIT_ALWAYS,
"ALWAYS",
ICON_NONE,
"Always",
"Inherit from scene defaults even if channel is not set to inherit"},
{BRUSH_MAPPING_INHERIT_CHANNEL,
"USE_CHANNEL",
ICON_NONE,
"Use Channel",
"Use channel's inheritance mode"},
{0, NULL, 0, NULL, NULL}};
prop = RNA_def_property(srna, "inherit_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "inherit_mode");
RNA_def_property_enum_items(prop, inherit_mode_items);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop,
"Inherit",
"Inherit from parent channel even if owning channel is set not to inherit.");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "inherit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "inherit_mode", BRUSH_MAPPING_INHERIT_ALWAYS);
RNA_def_property_ui_text(prop, "Inherit", "Inherit from scene channel");
RNA_def_property_boolean_funcs(
prop, "rna_BrushMapping_inherit_get", "rna_BrushMapping_inherit_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
prop = RNA_def_property(srna, "curve", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "CurveMapping");
@ -707,19 +749,19 @@ void RNA_def_brush_mapping(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_BrushMapping_curve_get", NULL, NULL, NULL);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, "BrushMapping", "type");
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, mapping_type_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Type", "Channel Type");
prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_ENABLED);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_MAPPING_ENABLED);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Enabled", "Input Mapping Is Enabled");
prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_INVERT);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_MAPPING_INVERT);
RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Enabled", "Input Mapping Is Enabled");
@ -752,7 +794,7 @@ void RNA_def_brush_mapping(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Function", "Input data function");
prop = RNA_def_property(srna, "ui_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_UI_EXPANDED);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_MAPPING_UI_EXPANDED);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Expanded", "View advanced properties");
}