Sculpt: More brush engine stuff, got automasking to work with it
* Sculpt now has an API to get brush channel settings. If a sculpt cache exists it will use the channels there (ss->cache->channels_final), otherwise it pulls them from a brush and Sculpt toolsettings. Exampes: float f = SCULPT_get_float(ss, "setting", sd, brush); itn i = SCULPT_get_int(ss, "setting", sd, brush); * Improved the UI a bit
This commit is contained in:
parent
645aee0835
commit
76beed9068
|
@ -108,7 +108,8 @@ class UnifiedPaintPanel:
|
|||
return None
|
||||
|
||||
@staticmethod
|
||||
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None, slider=False, header=False, expand=None):
|
||||
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
|
||||
slider=False, header=False, expand=None, toolsettings_only=False):
|
||||
""" Generalized way of adding brush options to the UI,
|
||||
along with their pen pressure setting and global toggle, if they exist. """
|
||||
ch = brush.channels.channels[prop_name]
|
||||
|
@ -119,6 +120,9 @@ class UnifiedPaintPanel:
|
|||
#if ch.ui_expanded:
|
||||
# layout = layout.box().column() #.column() is a bit more compact
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
layout = layout.box()
|
||||
|
||||
row = layout.row(align=True)
|
||||
|
||||
typeprop = "float_value"
|
||||
|
@ -139,18 +143,35 @@ class UnifiedPaintPanel:
|
|||
text = text.strip()
|
||||
|
||||
path = ""
|
||||
is_toolset = False
|
||||
|
||||
if ch.inherit:
|
||||
if ch.inherit or toolsettings_only:
|
||||
sd = context.tool_settings.sculpt
|
||||
#ensure channel exists in tool settings channel set
|
||||
sd.channels.ensure(ch)
|
||||
|
||||
finalch = sd.channels.channels[prop_name]
|
||||
is_toolset = True
|
||||
path = "tool_settings.sculpt.channels.channels[\"%s\"]" % ch.idname
|
||||
else:
|
||||
path = "tool_settings.sculpt.brush.channels.channels[\"%s\"]" % ch.idname
|
||||
|
||||
if expand is not None:
|
||||
if ch.type == "BITMASK":
|
||||
row.label(text=text)
|
||||
|
||||
if header:
|
||||
row.prop_menu_enum(finalch, typeprop)
|
||||
else:
|
||||
col = layout.column()
|
||||
col.emboss = "NONE"
|
||||
for item in finalch.enum_items:
|
||||
if item.identifier in finalch.flags_value:
|
||||
itemicon = "CHECKBOX_HLT"
|
||||
else:
|
||||
itemicon = "CHECKBOX_DEHLT"
|
||||
col.prop_enum(finalch, typeprop, item.identifier, icon=itemicon)
|
||||
|
||||
elif expand is not None:
|
||||
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider, expand=expand)
|
||||
else:
|
||||
row.prop(finalch, typeprop, icon=icon, text=text, slider=slider)
|
||||
|
@ -166,7 +187,15 @@ class UnifiedPaintPanel:
|
|||
# # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281
|
||||
# row.prop(ups, unified_name, text="", icon='BRUSHES_ALL')
|
||||
if not header and ch.type != "BOOL":
|
||||
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
|
||||
if ch.type == "BITMASK" and not toolsettings_only and ch == finalch:
|
||||
row.prop(ch, "inherit_if_unset", text="Combine With Defaults")
|
||||
|
||||
if not toolsettings_only:
|
||||
row.prop(ch, "inherit", text="", icon='BRUSHES_ALL')
|
||||
|
||||
if ch.type == "BITMASK":
|
||||
return
|
||||
|
||||
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
|
||||
|
||||
if ch.ui_expanded:
|
||||
|
@ -1163,6 +1192,18 @@ def brush_settings_advanced(layout, context, brush, popover=False):
|
|||
use_accumulate = capabilities.has_accumulate
|
||||
use_frontface = True
|
||||
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking", expand=False)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking_boundary_edges_propagation_steps")
|
||||
|
||||
"""
|
||||
col = layout.column(heading="Auto-Masking", align=True)
|
||||
|
||||
# topology automasking
|
||||
|
@ -1183,6 +1224,7 @@ def brush_settings_advanced(layout, context, brush, popover=False):
|
|||
col.prop(brush, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
col.prop(brush, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
col.prop(brush, "automasking_boundary_edges_propagation_steps")
|
||||
"""
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
|
|
@ -951,11 +951,26 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
|
|||
|
||||
col.separator()
|
||||
|
||||
brush = sculpt.brush
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking", toolsettings_only=True)
|
||||
UnifiedPaintPanel.channel_unified(
|
||||
layout.column(),
|
||||
context,
|
||||
brush,
|
||||
"automasking_boundary_edges_propagation_steps",
|
||||
toolsettings_only=True)
|
||||
|
||||
"""
|
||||
col = layout.column(heading="Auto-Masking", align=True)
|
||||
col.prop(sculpt, "use_automasking_topology", text="Topology")
|
||||
col.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
|
||||
col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
|
||||
col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
|
||||
"""
|
||||
|
||||
col.separator()
|
||||
col.operator("sculpt.set_limit_surface")
|
||||
|
|
|
@ -150,16 +150,18 @@ void BKE_brush_resolve_channels(struct Brush *brush, struct Sculpt *sd);
|
|||
|
||||
void BKE_brush_channelset_set_final_int(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
int value);
|
||||
|
||||
int BKE_brush_channelset_get_final_int(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
|
||||
int BKE_brush_channelset_get_int(BrushChannelSet *chset, char *idname, BrushMappingData *mapdata);
|
||||
bool BKE_brush_channelset_set_int(BrushChannelSet *chset, char *idname, int val);
|
||||
int BKE_brush_channelset_get_int(BrushChannelSet *chset,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val);
|
||||
|
||||
void BKE_brush_channel_set_int(BrushChannel *ch, int val);
|
||||
float BKE_brush_channel_get_int(BrushChannel *ch, BrushMappingData *mapdata);
|
||||
|
@ -172,18 +174,18 @@ void BKE_brush_channel_set_float(BrushChannel *ch, float val);
|
|||
|
||||
/* mapdata may be NULL */
|
||||
float BKE_brush_channelset_get_float(BrushChannelSet *chset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, char *idname, float val);
|
||||
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, const char *idname, float val);
|
||||
|
||||
float BKE_brush_channelset_get_final_float(BrushChannelSet *child,
|
||||
BrushChannelSet *parent,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata);
|
||||
|
||||
void BKE_brush_channelset_set_final_float(BrushChannelSet *child,
|
||||
BrushChannelSet *parent,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
float value);
|
||||
|
||||
void BKE_brush_init_toolsettings(struct Sculpt *sd);
|
||||
|
|
|
@ -641,7 +641,9 @@ void BKE_brush_resolve_channels(Brush *brush, Sculpt *sd)
|
|||
BKE_brush_channelset_merge(brush->channels_final, brush->channels, sd->channels);
|
||||
}
|
||||
|
||||
int BKE_brush_channelset_get_int(BrushChannelSet *chset, char *idname, BrushMappingData *mapdata)
|
||||
int BKE_brush_channelset_get_int(BrushChannelSet *chset,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
|
||||
|
||||
|
@ -709,7 +711,7 @@ void BKE_brush_channel_set_int(BrushChannel *ch, int val)
|
|||
|
||||
int BKE_brush_channelset_get_final_int(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(brushset, idname);
|
||||
|
@ -733,7 +735,7 @@ int BKE_brush_channelset_get_final_int(BrushChannelSet *brushset,
|
|||
|
||||
void BKE_brush_channelset_set_final_int(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
int value)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(brushset, idname);
|
||||
|
@ -757,7 +759,7 @@ void BKE_brush_channelset_set_final_int(BrushChannelSet *brushset,
|
|||
|
||||
float BKE_brush_channelset_get_final_float(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(brushset, idname);
|
||||
|
@ -781,7 +783,7 @@ float BKE_brush_channelset_get_final_float(BrushChannelSet *brushset,
|
|||
|
||||
void BKE_brush_channelset_set_final_float(BrushChannelSet *brushset,
|
||||
BrushChannelSet *toolset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
float value)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(brushset, idname);
|
||||
|
@ -804,7 +806,7 @@ void BKE_brush_channelset_set_final_float(BrushChannelSet *brushset,
|
|||
}
|
||||
|
||||
float BKE_brush_channelset_get_float(BrushChannelSet *chset,
|
||||
char *idname,
|
||||
const char *idname,
|
||||
BrushMappingData *mapdata)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
|
||||
|
@ -875,7 +877,7 @@ void BKE_brush_channel_set_float(BrushChannel *ch, float val)
|
|||
ch->fvalue = val;
|
||||
}
|
||||
|
||||
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, char *idname, float val)
|
||||
bool BKE_brush_channelset_set_float(BrushChannelSet *chset, const char *idname, float val)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
|
||||
|
||||
|
@ -889,7 +891,7 @@ bool BKE_brush_channelset_set_float(BrushChannelSet *chset, char *idname, float
|
|||
return true;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT bool BKE_brush_channelset_set_int(BrushChannelSet *chset, char *idname, int val)
|
||||
ATTR_NO_OPT bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val)
|
||||
{
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
|
||||
|
||||
|
|
|
@ -320,7 +320,7 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
{
|
||||
.name = "Automasking",
|
||||
.idname = "automasking",
|
||||
.flag = BRUSH_CHANNEL_INHERIT_IF_UNSET | BRUSH_CHANNEL_INHERIT,
|
||||
.flag = BRUSH_CHANNEL_INHERIT_IF_UNSET,
|
||||
.type = BRUSH_CHANNEL_BITMASK,
|
||||
.enumdef = {
|
||||
{BRUSH_AUTOMASKING_BOUNDARY_EDGES, "BOUNDARY_EDGE", ICON_NONE, "Boundary Edges", ""},
|
||||
|
@ -444,7 +444,12 @@ BrushChannelType brush_builtin_channels[] = {
|
|||
MAKE_FLOAT_EX("dyntopo_detail_size", "Detail Size", "Detail Size", 8.0f, 0.1f, 100.0f, 0.001f, 500.0f),
|
||||
MAKE_FLOAT_EX("dyntopo_constant_detail", "Constaint Detail", "", 3.0f, 0.001f, 1000.0f, 0.0001, FLT_MAX),
|
||||
MAKE_FLOAT_EX("dyntopo_spacing", "Spacing", "Dyntopo Spacing", 35.0f, 0.01f, 300.0f, 0.001f, 50000.0f),
|
||||
MAKE_FLOAT_EX("dyntopo_radius_scale", "Radius Scale", "Scale brush radius for dyntopo radius", 1.0f, 0.001f, 3.0f, 0.0001f, 100.0f)
|
||||
MAKE_FLOAT_EX("dyntopo_radius_scale", "Radius Scale", "Scale brush radius for dyntopo radius", 1.0f, 0.001f, 3.0f, 0.0001f, 100.0f),
|
||||
MAKE_FLOAT("concave_mask_factor", "Cavity Factor", "", 0.35f, 0.0f, 1.0f),
|
||||
MAKE_INT_EX("automasking_boundary_edges_propagation_steps", "Propagation Steps",
|
||||
"Distance where boundary edge automasking is going to protect vertices "
|
||||
"from the fully masked edge", 1, 1, 20, 1, 3),
|
||||
|
||||
};
|
||||
|
||||
/* clang-format on */
|
||||
|
@ -536,6 +541,8 @@ static BrushSettingsMap brush_settings_map[] = {
|
|||
DEF(wet_persistence, wet_persistence, FLOAT, FLOAT)
|
||||
DEF(density, density, FLOAT, FLOAT)
|
||||
DEF(tip_scale_x, tip_scale_x, FLOAT, FLOAT)
|
||||
DEF(concave_mask_factor, concave_mask_factor, FLOAT, FLOAT)
|
||||
DEF(automasking_boundary_edges_propagation_steps, automasking_boundary_edges_propagation_steps, INT, INT)
|
||||
};
|
||||
|
||||
static const int brush_settings_map_len = ARRAY_SIZE(brush_settings_map);
|
||||
|
@ -881,7 +888,8 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
ADDCH("normal_radius_factor");
|
||||
|
||||
ADDCH("automasking");
|
||||
|
||||
ADDCH("automasking_boundary_edges_propagation_steps");
|
||||
ADDCH("concave_mask_factor");
|
||||
ADDCH("dyntopo_disabled");
|
||||
ADDCH("dyntopo_mode")->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
ADDCH("dyntopo_detail_range")->flag |= BRUSH_CHANNEL_INHERIT;
|
||||
|
@ -1026,6 +1034,8 @@ void BKE_brush_check_toolsettings(Sculpt *sd)
|
|||
|
||||
ADDCH("radius");
|
||||
ADDCH("strength");
|
||||
ADDCH("automasking_boundary_edges_propagation_steps");
|
||||
ADDCH("concave_mask_factor");
|
||||
ADDCH("automasking");
|
||||
ADDCH("topology_rake_mode");
|
||||
|
||||
|
|
|
@ -134,6 +134,40 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
|
|||
BrushActionFunc action,
|
||||
UnifiedPaintSettings *ups);
|
||||
|
||||
/* Sculpt API to get brush channel data
|
||||
If ss->cache exists then ss->cache->channels_final
|
||||
will be used, otherwise brush and tool settings channels
|
||||
will be used (taking inheritence into account).
|
||||
*/
|
||||
|
||||
ATTR_NO_OPT float SCULPT_get_float(const SculptSession *ss,
|
||||
const char *idname,
|
||||
const Sculpt *sd,
|
||||
const Brush *br)
|
||||
{
|
||||
if (ss->cache && ss->cache->channels_final) {
|
||||
return BKE_brush_channelset_get_float(
|
||||
ss->cache->channels_final, idname, &ss->cache->input_mapping);
|
||||
}
|
||||
else {
|
||||
return BKE_brush_channelset_get_final_float(br->channels, sd->channels, idname, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT int SCULPT_get_int(const SculptSession *ss,
|
||||
const char *idname,
|
||||
const Sculpt *sd,
|
||||
const Brush *br)
|
||||
{
|
||||
if (ss->cache && ss->cache->channels_final) {
|
||||
return BKE_brush_channelset_get_int(
|
||||
ss->cache->channels_final, idname, &ss->cache->input_mapping);
|
||||
}
|
||||
else {
|
||||
return BKE_brush_channelset_get_final_int(br->channels, sd->channels, idname, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sculpt PBVH abstraction API
|
||||
*
|
||||
* This is read-only, for writing use PBVH vertex iterators. There vd.index matches
|
||||
|
@ -8835,7 +8869,7 @@ ATTR_NO_OPT static void SCULPT_run_command_list(
|
|||
BKE_brush_commandlist_start(list, brush, ss->cache->channels_final);
|
||||
|
||||
// this does a more high-level check then SCULPT_TOOL_HAS_DYNTOPO;
|
||||
bool has_dyntopo = SCULPT_stroke_is_dynamic_topology(ss, brush);
|
||||
bool has_dyntopo = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
|
||||
bool all_nodes_undo = false;
|
||||
bool cloth_nodes_undo = false;
|
||||
|
||||
|
@ -9239,7 +9273,9 @@ ATTR_NO_OPT static void SCULPT_run_command_list(
|
|||
SCULPT_uv_brush(sd, ob, nodes, totnode);
|
||||
break;
|
||||
case SCULPT_TOOL_TOPOLOGY_RAKE:
|
||||
bmesh_topology_rake(sd, ob, nodes, totnode, brush2->alpha);
|
||||
if (ss->bm) {
|
||||
bmesh_topology_rake(sd, ob, nodes, totnode, brush2->alpha);
|
||||
}
|
||||
break;
|
||||
case SCULPT_TOOL_DYNTOPO:
|
||||
if (has_dyntopo) {
|
||||
|
|
|
@ -73,12 +73,15 @@ AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool SCULPT_is_automasking_mode_enabled(Sculpt *sd, const Brush *br, const eAutomasking_flag mode)
|
||||
bool SCULPT_is_automasking_mode_enabled(const SculptSession *ss,
|
||||
const Sculpt *sd,
|
||||
const Brush *br,
|
||||
const eAutomasking_flag mode)
|
||||
{
|
||||
if (br) {
|
||||
return br->automasking_flags & mode || sd->automasking_flags & mode;
|
||||
}
|
||||
return sd->automasking_flags & mode;
|
||||
int flag = BKE_brush_channelset_get_int(
|
||||
ss->cache->channels_final, "automasking", &ss->cache->input_mapping);
|
||||
|
||||
return flag & mode;
|
||||
}
|
||||
|
||||
bool SCULPT_is_automasking_enabled(Sculpt *sd, const SculptSession *ss, const Brush *br)
|
||||
|
@ -88,34 +91,20 @@ bool SCULPT_is_automasking_enabled(Sculpt *sd, const SculptSession *ss, const Br
|
|||
return false;
|
||||
}*/
|
||||
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
return true;
|
||||
}
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
return true;
|
||||
}
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
return true;
|
||||
}
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
return true;
|
||||
}
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, br, BRUSH_AUTOMASKING_CONCAVITY)) {
|
||||
if (br && br->concave_mask_factor == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
int flag = SCULPT_get_int(ss, "automasking", sd, br);
|
||||
|
||||
if (flag == BRUSH_AUTOMASKING_CONCAVITY) {
|
||||
return SCULPT_get_float(ss, "concave_mask_factor", sd, br) > 0.0f;
|
||||
}
|
||||
|
||||
return false;
|
||||
return flag != 0;
|
||||
}
|
||||
|
||||
static int sculpt_automasking_mode_effective_bits(Sculpt *sculpt, const Brush *brush)
|
||||
static int sculpt_automasking_mode_effective_bits(SculptSession *ss,
|
||||
Sculpt *sculpt,
|
||||
const Brush *brush)
|
||||
{
|
||||
if (brush) {
|
||||
return sculpt->automasking_flags | brush->automasking_flags;
|
||||
}
|
||||
return sculpt->automasking_flags;
|
||||
return SCULPT_get_int(ss, "automasking", sculpt, brush);
|
||||
}
|
||||
|
||||
static float sculpt_concavity_factor(AutomaskingCache *automasking, float fac)
|
||||
|
@ -130,18 +119,27 @@ static float sculpt_concavity_factor(AutomaskingCache *automasking, float fac)
|
|||
return fac;
|
||||
}
|
||||
|
||||
static bool SCULPT_automasking_needs_factors_cache(Sculpt *sd, const Brush *brush)
|
||||
static int automasking_get_propegation(SculptSession *ss)
|
||||
{
|
||||
return BKE_brush_channelset_get_int(ss->cache->channels_final,
|
||||
"automasking_boundary_edges_propagation_steps",
|
||||
&ss->cache->input_mapping);
|
||||
}
|
||||
|
||||
static bool SCULPT_automasking_needs_factors_cache(SculptSession *ss,
|
||||
Sculpt *sd,
|
||||
const Brush *brush)
|
||||
{
|
||||
|
||||
const int automasking_flags = sculpt_automasking_mode_effective_bits(sd, brush);
|
||||
const int automasking_flags = sculpt_automasking_mode_effective_bits(ss, sd, brush);
|
||||
if (automasking_flags & BRUSH_AUTOMASKING_TOPOLOGY) {
|
||||
return true;
|
||||
}
|
||||
if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_EDGES) {
|
||||
return brush && brush->automasking_boundary_edges_propagation_steps != 1;
|
||||
return brush && automasking_get_propegation(ss) != 1;
|
||||
}
|
||||
if (automasking_flags & BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS) {
|
||||
return brush && brush->automasking_boundary_edges_propagation_steps != 1;
|
||||
return brush && automasking_get_propegation(ss) != 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -157,7 +155,10 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
|||
return mask;
|
||||
}
|
||||
|
||||
do_concave = ss->cache && ss->cache->brush && ss->cache->brush->concave_mask_factor > 0.0f &&
|
||||
float concave_factor = BKE_brush_channelset_get_float(
|
||||
ss->cache->channels_final, "concave_mask_factor", &ss->cache->input_mapping);
|
||||
|
||||
do_concave = ss->cache && concave_factor > 0.0f &&
|
||||
(automasking->settings.flags & BRUSH_AUTOMASKING_CONCAVITY);
|
||||
|
||||
/* If the cache is initialized with valid info, use the cache. This is used when the
|
||||
|
@ -321,8 +322,6 @@ static void sculpt_face_sets_automasking_init(Sculpt *sd,
|
|||
*(float *)SCULPT_temp_cdata_get(vertex, factorlayer) = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#define EDGE_DISTANCE_INF -1
|
||||
|
@ -334,11 +333,6 @@ void SCULPT_boundary_automasking_init(Object *ob,
|
|||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (!ss->pmap) {
|
||||
BLI_assert_msg(0, "Boundary Edges masking: pmap missing");
|
||||
return;
|
||||
}
|
||||
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
int *edge_distance = MEM_callocN(sizeof(int) * totvert, "automask_factor");
|
||||
|
||||
|
@ -346,6 +340,7 @@ void SCULPT_boundary_automasking_init(Object *ob,
|
|||
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
edge_distance[i] = EDGE_DISTANCE_INF;
|
||||
|
||||
switch (mode) {
|
||||
case AUTOMASK_INIT_BOUNDARY_EDGES:
|
||||
if (SCULPT_vertex_is_boundary(ss, vertex, SCULPT_BOUNDARY_MESH)) {
|
||||
|
@ -397,10 +392,11 @@ static void SCULPT_automasking_cache_settings_update(AutomaskingCache *automaski
|
|||
Sculpt *sd,
|
||||
const Brush *brush)
|
||||
{
|
||||
automasking->settings.flags = sculpt_automasking_mode_effective_bits(sd, brush);
|
||||
automasking->settings.flags = sculpt_automasking_mode_effective_bits(ss, sd, brush);
|
||||
|
||||
automasking->settings.initial_face_set = SCULPT_active_face_set_get(ss);
|
||||
automasking->settings.concave_factor = brush ? brush->concave_mask_factor : 0.0f;
|
||||
automasking->settings.concave_factor = BKE_brush_channelset_get_float(
|
||||
ss->cache->channels_final, "concave_mask_factor", &ss->cache->input_mapping);
|
||||
}
|
||||
|
||||
float SCULPT_calc_concavity(SculptSession *ss, SculptVertRef vref)
|
||||
|
@ -420,7 +416,7 @@ float SCULPT_calc_concavity(SculptSession *ss, SculptVertRef vref)
|
|||
}
|
||||
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
|
||||
|
||||
if (!tot) {
|
||||
if (tot == 0.0f) {
|
||||
return 0.5f;
|
||||
}
|
||||
|
||||
|
@ -469,10 +465,11 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
|
|||
}
|
||||
|
||||
AutomaskingCache *automasking = MEM_callocN(sizeof(AutomaskingCache), "automasking cache");
|
||||
|
||||
SCULPT_automasking_cache_settings_update(automasking, ss, sd, brush);
|
||||
SCULPT_boundary_info_ensure(ob);
|
||||
|
||||
if (!SCULPT_automasking_needs_factors_cache(sd, brush)) {
|
||||
if (!SCULPT_automasking_needs_factors_cache(ss, sd, brush)) {
|
||||
return automasking;
|
||||
}
|
||||
|
||||
|
@ -502,16 +499,14 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
|
|||
*f = 1.0f;
|
||||
}
|
||||
|
||||
const int boundary_propagation_steps = brush ?
|
||||
brush->automasking_boundary_edges_propagation_steps :
|
||||
1;
|
||||
const int boundary_propagation_steps = automasking_get_propegation(ss);
|
||||
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
if (SCULPT_is_automasking_mode_enabled(ss, sd, brush, BRUSH_AUTOMASKING_TOPOLOGY)) {
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
SCULPT_topology_automasking_init(sd, ob, automasking->factorlayer);
|
||||
}
|
||||
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
if (SCULPT_is_automasking_mode_enabled(ss, sd, brush, BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS)) {
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
SCULPT_boundary_automasking_init(ob,
|
||||
AUTOMASK_INIT_BOUNDARY_FACE_SETS,
|
||||
|
@ -524,17 +519,17 @@ AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush,
|
|||
return automasking;
|
||||
}
|
||||
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
if (SCULPT_is_automasking_mode_enabled(ss, sd, brush, BRUSH_AUTOMASKING_FACE_SETS)) {
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
sculpt_face_sets_automasking_init(sd, ob, automasking->factorlayer);
|
||||
}
|
||||
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
if (SCULPT_is_automasking_mode_enabled(ss, sd, brush, BRUSH_AUTOMASKING_BOUNDARY_EDGES)) {
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
SCULPT_boundary_automasking_init(
|
||||
ob, AUTOMASK_INIT_BOUNDARY_EDGES, boundary_propagation_steps, automasking->factorlayer);
|
||||
}
|
||||
if (SCULPT_is_automasking_mode_enabled(sd, brush, BRUSH_AUTOMASKING_CONCAVITY)) {
|
||||
if (SCULPT_is_automasking_mode_enabled(ss, sd, brush, BRUSH_AUTOMASKING_CONCAVITY)) {
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
SCULPT_concavity_automasking_init(ob, brush, automasking, automasking->factorlayer);
|
||||
}
|
||||
|
|
|
@ -253,6 +253,18 @@ typedef enum SculptCornerType {
|
|||
SCULPT_CORNER_SHARP = 1 << 3
|
||||
} SculptCornerType;
|
||||
|
||||
/* Sculpt API to get brush channel data
|
||||
If ss->cache exists then ss->cache->channels_final
|
||||
will be used, otherwise brush and tool settings channels
|
||||
will be used (taking inheritence into account).
|
||||
*/
|
||||
|
||||
float SCULPT_get_float(const SculptSession *ss,
|
||||
const char *idname,
|
||||
const Sculpt *sd,
|
||||
const Brush *br);
|
||||
int SCULPT_get_int(const SculptSession *ss, const char *idname, const Sculpt *sd, const Brush *br);
|
||||
|
||||
SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
|
||||
const SculptVertRef index,
|
||||
SculptCornerType cornertype);
|
||||
|
@ -450,7 +462,10 @@ struct AutomaskingCache *SCULPT_automasking_active_cache_get(SculptSession *ss);
|
|||
struct AutomaskingCache *SCULPT_automasking_cache_init(Sculpt *sd, const Brush *brush, Object *ob);
|
||||
void SCULPT_automasking_cache_free(struct AutomaskingCache *automasking);
|
||||
|
||||
bool SCULPT_is_automasking_mode_enabled(Sculpt *sd, const Brush *br, const eAutomasking_flag mode);
|
||||
bool SCULPT_is_automasking_mode_enabled(const SculptSession *ss,
|
||||
const Sculpt *sd,
|
||||
const Brush *br,
|
||||
const eAutomasking_flag mode);
|
||||
bool SCULPT_is_automasking_enabled(Sculpt *sd, const SculptSession *ss, const Brush *br);
|
||||
|
||||
typedef enum eBoundaryAutomaskMode {
|
||||
|
@ -1081,6 +1096,7 @@ typedef struct AutomaskingCache {
|
|||
* initialized in #SCULPT_automasking_cache_init when needed. */
|
||||
// float *factor;
|
||||
SculptCustomLayer *factorlayer;
|
||||
float concave_mask_factor;
|
||||
} AutomaskingCache;
|
||||
|
||||
typedef struct StrokeCache {
|
||||
|
|
|
@ -1500,13 +1500,13 @@ bool RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *v
|
|||
return 0;
|
||||
}
|
||||
|
||||
void RNA_property_enum_items_ex(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const bool use_static,
|
||||
const EnumPropertyItem **r_item,
|
||||
int *r_totitem,
|
||||
bool *r_free)
|
||||
ATTR_NO_OPT void RNA_property_enum_items_ex(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
const bool use_static,
|
||||
const EnumPropertyItem **r_item,
|
||||
int *r_totitem,
|
||||
bool *r_free)
|
||||
{
|
||||
EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
#include "DNA_sculpt_brush_types.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
static EnumPropertyItem null_enum[2] = {{0, "null", 0, 0}, {0, NULL, 0, NULL, NULL}};
|
||||
static EnumPropertyItem null_enum[2] = {{0, "null", ICON_NONE, "null"}, {0, NULL, 0, NULL, NULL}};
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
|
@ -241,6 +241,50 @@ ATTR_NO_OPT const EnumPropertyItem *rna_BrushChannel_enum_value_get_items(struct
|
|||
return ch->def->rna_enumdef;
|
||||
}
|
||||
|
||||
static int rna_enum_check_separator(CollectionPropertyIterator *UNUSED(iter), void *data)
|
||||
{
|
||||
EnumPropertyItem *item = (EnumPropertyItem *)data;
|
||||
|
||||
return (item->identifier[0] == 0);
|
||||
}
|
||||
|
||||
static void rna_BrushChannel_enum_items_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
|
||||
{
|
||||
/* EnumPropertyRNA *eprop; */ /* UNUSED */
|
||||
const EnumPropertyItem *item = NULL;
|
||||
int totitem;
|
||||
bool free;
|
||||
|
||||
BrushChannel *ch = (BrushChannel *)ptr->data;
|
||||
|
||||
if (!ch->def || !ELEM(ch->type, BRUSH_CHANNEL_ENUM, BRUSH_CHANNEL_BITMASK)) {
|
||||
if (!ch->def) {
|
||||
printf("%s: channel '%s' had no definition\n", __func__, ch->idname);
|
||||
}
|
||||
else {
|
||||
printf("%s: channel '%s' is not an enum/bitmask\n", __func__, ch->idname);
|
||||
}
|
||||
|
||||
item = null_enum;
|
||||
|
||||
rna_iterator_array_begin(
|
||||
iter, (void *)item, sizeof(EnumPropertyItem), 0, free, rna_enum_check_separator);
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_brush_channeltype_rna_check(ch->def, lookup_icon_id);
|
||||
|
||||
totitem = 0;
|
||||
while (ch->def->rna_enumdef[totitem].name) {
|
||||
totitem++;
|
||||
}
|
||||
|
||||
item = ch->def->rna_enumdef;
|
||||
|
||||
rna_iterator_array_begin(
|
||||
iter, (void *)item, sizeof(EnumPropertyItem), totitem, free, rna_enum_check_separator);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static EnumPropertyItem mapping_type_items[] = {
|
||||
|
@ -401,6 +445,20 @@ void RNA_def_brush_channel(BlenderRNA *brna)
|
|||
"rna_BrushChannel_enum_value_set",
|
||||
"rna_BrushChannel_enum_value_get_items");
|
||||
|
||||
prop = RNA_def_property(srna, "enum_items", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_ANIMATABLE);
|
||||
RNA_def_property_struct_type(prop, "EnumPropertyItem");
|
||||
RNA_def_property_collection_funcs(prop,
|
||||
"rna_BrushChannel_enum_items_begin",
|
||||
"rna_iterator_array_next",
|
||||
"rna_iterator_array_end",
|
||||
"rna_iterator_array_get",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
RNA_def_property_ui_text(prop, "Items", "Possible values for the property");
|
||||
|
||||
prop = RNA_def_property(srna, "flags_value", PROP_ENUM, PROP_UNIT_NONE);
|
||||
RNA_def_property_ui_text(prop, "Flags Value", "Flags values");
|
||||
|
||||
|
|
Loading…
Reference in New Issue