Sculpt: more brush stuff

* Move more dyntopo settings to brush channels
* Implemented the unprojected radius hack in
  the new brush system.  I'm not really happy
  with it, but doing it properly is going to
  take some thought.
This commit is contained in:
Joseph Eagar 2021-09-24 02:38:20 -07:00
parent 33cd635a82
commit eb9a5e8f8b
31 changed files with 779 additions and 321 deletions

View File

@ -70,9 +70,9 @@ static int check_if_canceled(float progress,
return cancel;
}
ATTR_NO_OPT void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
void QFLOW_quadriflow_remesh(QuadriflowRemeshData *qrd,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
Parametrizer field;
VertexMap vertexMap;

View File

@ -27,9 +27,10 @@ channel_name_map = {
"auto_smooth_radius_factor": "autosmooth_radius_scale",
"boundary_smooth_factor": "boundary_smooth",
"autosmooth_fset_slide": "fset_slide",
"topology_rake_factor": "topology_rake"
"topology_rake_factor": "topology_rake",
"use_locked_size" : "radius_unit"
};
expand_channels = {"direction"}
expand_channels = {"direction", "radius_unit", "automasking"}
def template_curve(layout, base, propname, full_path):
layout.template_curve_mapping(base, propname, brush=True)
@ -125,11 +126,64 @@ class UnifiedPaintPanel:
return None
@staticmethod
def get_channel(context, brush, prop_name, toolsettings_only=False):
ch = brush.channels.channels[prop_name]
if ch.inherit or toolsettings_only:
sd = context.tool_settings.sculpt
#ensure channel exists in tool settings channel set
sd.channels.ensure(ch)
ch = sd.channels.channels[prop_name]
return ch
def get_channel_value(context, brush, prop_name, toolsettings_only=False):
ch = brush.channels.channels[prop_name]
if ch.inherit or toolsettings_only:
sd = context.tool_settings.sculpt
#ensure channel exists in tool settings channel set
sd.channels.ensure(ch)
ch = sd.channels.channels[prop_name]
if ch.type == "FLOAT":
return ch.float_value
elif ch.type == "INT":
return ch.int_value
elif ch.type == "ENUM":
return ch.enum_value
elif ch.type == "BITMASK":
return ch.flags_value
elif ch.type == "VEC3":
return ch.color3_value
elif ch.type == "VEC4":
return ch.color4_value
elif ch.type == "CURVE":
return ch.curve
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None,
slider=False, header=False, show_reorder=False, expand=None, toolsettings_only=False, ui_editing=True):
""" Generalized way of adding brush options to the UI,
along with their pen pressure setting and global toggle, if they exist. """
if context.mode != "SCULPT":
return self.prop_unified(layout, context, brush, prop_name, icon=icon, text=text, slider=slider, header=header, expand=expand)
if prop_name == "size":
prop_name = "radius"
elif prop_name == "use_locked_size":
prop_name = "radius_unit"
ch = brush.channels.channels[prop_name]
#dynamically switch to unprojected radius if necassary
if prop_name == "radius":
size_mode = brush.channels.channels["radius_unit"].enum_value == "SCENE"
if size_mode:
prop_name = "unprojected_radius"
ch = brush.channels.channels[prop_name]
finalch = ch
if prop_name in expand_channels:
@ -141,7 +195,7 @@ class UnifiedPaintPanel:
# layout = layout.box().column() #.column() is a bit more compact
if ch.type == "BITMASK":
layout = layout.box()
layout = layout.column(align=True)
row = layout.row(align=True)
@ -160,8 +214,11 @@ class UnifiedPaintPanel:
typeprop = "color3_value"
elif ch.type == "VEC4":
typeprop = "color4_value"
if text is None:
text = ch.name
if len(text) == 0: #auto-generate from idname
s = prop_name.lower().replace("_", " ").split(" ");
text = ''
for k in s:
@ -209,19 +266,34 @@ class UnifiedPaintPanel:
template_curve(layout, finalch.curve, "curve", path2)
elif ch.type == "BITMASK":
row.label(text=text)
if header:
row.prop_menu_enum(finalch, typeprop)
if header or not expand:
row.label(text=text)
row.prop_menu_enum(finalch, typeprop, text=text)
else:
col = layout.column()
col.emboss = "NONE"
for item in finalch.enum_items:
#why is it so hard to make bitflag checkboxes?
row.label(text=text)
col = layout.row(align=True)
#col.emboss = "NONE"
row1 = col.column(align=True)
row2 = col.column(align=True)
row1.emboss = "NONE"
row2.emboss = "NONE"
row1.use_property_split = False
row2.use_property_split = False
row1.use_property_decorate = False
row2.use_property_decorate = False
for j, item in enumerate(finalch.enum_items):
row3 = row1 if j % 2 == 0 else row2
if item.identifier in finalch.flags_value:
itemicon = "CHECKBOX_HLT"
else:
itemicon = "CHECKBOX_DEHLT"
col.prop_enum(finalch, typeprop, item.identifier, icon=itemicon)
row3.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)
@ -274,7 +346,7 @@ class UnifiedPaintPanel:
row2.prop(mp, "enabled", text="", icon="STYLUS_PRESSURE")
row2.prop(mp0, "ui_expanded", text="", icon="TRIA_DOWN" if mp.ui_expanded else "TRIA_RIGHT")
if mp.ui_expanded:
if mp0.ui_expanded:
layout.template_curve_mapping(mp, "curve", brush=True)
col = layout.column(align=True)
@ -306,16 +378,18 @@ class UnifiedPaintPanel:
text=None,
slider=False,
header=False,
expand=None
):
""" Generalized way of adding brush options to the UI,
along with their pen pressure setting and global toggle, if they exist. """
if prop_name in channel_name_map:
prop_name = channel_name_map[prop_name]
if context.mode == "SCULPT":
if prop_name in channel_name_map:
prop_name = channel_name_map[prop_name]
if prop_name in brush.channels.channels:
# def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None, slider=False, header=False):
return UnifiedPaintPanel.channel_unified(layout, context, brush, prop_name, icon=icon, text=text, slider=slider, header=header)
if prop_name in brush.channels.channels:
# def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=True, text=None, slider=False, header=False):
return UnifiedPaintPanel.channel_unified(layout, context, brush, prop_name, icon=icon, text=text, slider=slider, header=header)
row = layout.row(align=True)
ups = context.tool_settings.unified_paint_settings
@ -323,7 +397,10 @@ class UnifiedPaintPanel:
if unified_name and getattr(ups, unified_name):
prop_owner = ups
row.prop(prop_owner, prop_name, icon=icon, text=text, slider=slider)
if expand is not None:
row.prop(prop_owner, prop_name, icon=icon, text=text, slider=slider, expand=expand)
else:
row.prop(prop_owner, prop_name, icon=icon, text=text, slider=slider)
if pressure_name:
row.prop(brush, pressure_name, text="")
@ -1267,27 +1344,19 @@ def brush_shared_settings(layout, context, brush, popover=False):
layout,
context,
brush,
"radius" if size_prop == "size" else size_prop.upper(),
size_prop,
text="Radius",
slider=True,
)
if size_mode:
layout.row().prop(size_owner, "use_locked_size", expand=True)
layout.separator()
elif size or size_mode:
if size:
UnifiedPaintPanel.prop_unified(
layout,
#layout.row().prop(size_owner, "use_locked_size", expand=True)
UnifiedPaintPanel.channel_unified(
layout.row(),
context,
brush,
size_prop,
unified_name="use_unified_size",
pressure_name="use_pressure_size",
text="Radius",
slider=True,
"use_locked_size",
expand=True
)
if size_mode:
layout.row().prop(size_owner, "use_locked_size", expand=True)
layout.separator()
if strength:
@ -1429,7 +1498,7 @@ def brush_settings_advanced(layout, context, brush, popover=False):
layout.column(),
context,
brush,
"automasking", expand=False)
"automasking", expand=True)
UnifiedPaintPanel.channel_unified(
layout.column(),
context,

View File

@ -830,6 +830,47 @@ class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
def draw(self, context):
layout = self.layout
brush = context.tool_settings.sculpt.brush
ch = brush.channels.channels["dyntopo_mode"]
if ch.inherit:
row = layout.row()
row.prop(ch, "show_in_workspace", text="", icon="HIDE_OFF")
row.label(text="Remesher Options")
row.prop(ch, "inherit", text="", icon="BRUSHES_ALL")
else:
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"dyntopo_mode",
text="Remesher Options",
expand=True
)
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
"dyntopo_detail_mode",
text="Detail Mode",
expand=False
)
keys = ["dyntopo_spacing", "dyntopo_detail_size", "dyntopo_detail_range", "dyntopo_detail_percent",
"dyntopo_constant_detail", "dyntopo_radius_scale"]
for k in keys:
UnifiedPaintPanel.channel_unified(
layout,
context,
brush,
k,
slider=True
)
return
layout.use_property_split = True
layout.use_property_decorate = False
@ -881,7 +922,60 @@ class VIEW3D_PT_sculpt_dyntopo_advanced(Panel, View3DPaintPanel):
do_prop("mode")
do_prop("radius_scale")
# TODO, move to space_view3d.py
from bpy.types import Operator
from bpy.props import EnumProperty
class SCULPT_OT_set_dyntopo_mode (Operator):
"""Set refine mode"""
bl_label = "Set Detail Mode"
bl_idname = "sculpt.set_dyntopo_mode"
mode: EnumProperty(items=[
("SC", "Subdivide Collapse", "", 1),
("S", "Subdivide Edges", "", 2),
("C", "Collapse Edges", "", 3)
])
def execute(self, context):
brush = context.tool_settings.sculpt.brush
ch = UnifiedPaintPanel.get_channel(context, brush, "dyntopo_mode")
oldf = set()
for f in ch.flags_value:
if f not in ["SUBDIVIDE", "COLLAPSE"]:
oldf.add(f)
if self.mode == "SC":
ch.flags_value = oldf.union({"SUBDIVIDE", "COLLAPSE"})
elif self.mode == "S":
ch.flags_value = oldf.union({"SUBDIVIDE"})
elif self.mode == "C":
ch.flags_value = oldf.union({"COLLAPSE"})
return {'FINISHED'}
def set_dyntopo_mode_button(layout, context):
brush = context.tool_settings.sculpt.brush
ch = brush.channels.channels["dyntopo_mode"]
finalch = UnifiedPaintPanel.get_channel(context, brush, "dyntopo_mode")
if "SUBDIVIDE" in finalch.flags_value and "COLLAPSE" in finalch.flags_value:
text = "Subdivide Collapse"
elif "SUBDIVIDE" in finalch.flags_value:
text = "Subdivide Edges"
elif "COLLAPSE" in finalch.flags_value:
text = "Collapse Edges"
else:
text = ""
row = layout.row(heading="Refine Method")
row.use_property_split = False
row.operator_menu_enum("sculpt.set_dyntopo_mode", "mode", text=text)
row.prop(ch, "inherit", text="", icon="BRUSHES_ALL")
class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
bl_label = "Dynamic Mode"
@ -912,7 +1006,7 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
sculpt = tool_settings.sculpt
settings = self.paint_settings(context)
brush = settings.brush
col = layout.column()
col.active = context.sculpt_object.use_dynamic_topology_sculpting
@ -920,27 +1014,87 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
sub = col.column()
sub.active = (brush and brush.sculpt_tool != 'MASK')
if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
detail_mode = UnifiedPaintPanel.get_channel_value(context, brush, "dyntopo_detail_mode")
if detail_mode in {'CONSTANT', 'MANUAL'}:
row = sub.row(align=True)
row.prop(sculpt, "constant_detail_resolution")
#row.prop(sculpt, "constant_detail_resolution")
UnifiedPaintPanel.channel_unified(
row,
context,
brush,
"dyntopo_constant_detail",
text="Constant Resolution",
#slider=True,
ui_editing=False,
pressure=False
)
props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
props.mode = 'DYNTOPO'
elif (sculpt.detail_type_method == 'BRUSH'):
sub.prop(sculpt, "detail_percent")
elif detail_mode == 'BRUSH':
UnifiedPaintPanel.channel_unified(
sub,
context,
brush,
"dyntopo_detail_percent",
text="Detail Percent",
#slider=True,
ui_editing=False,
pressure=False
)
else:
sub.prop(sculpt, "detail_size")
sub.prop(sculpt, "detail_refine_method", text="Refine Method")
sub.prop(sculpt, "detail_type_method", text="Detailing")
UnifiedPaintPanel.channel_unified(
sub,
context,
brush,
"dyntopo_detail_size",
text="Detail Size",
#slider=True,
ui_editing=False,
pressure=False
)
if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}:
#"""
UnifiedPaintPanel.channel_unified(
sub,
context,
brush,
"dyntopo_detail_mode",
text="Detailing",
expand=False,
ui_editing=False
)
set_dyntopo_mode_button(sub, context)
col2 = col.row() #sub.column()
ch = UnifiedPaintPanel.get_channel(context, brush, "dyntopo_mode")
col2.use_property_split = False
col2.prop_enum(ch, "flags_value", "CLEANUP", icon = "CHECKBOX_HLT" if "CLEANUP" in ch.flags_value else "CHECKBOX_DEHLT")
"""
UnifiedPaintPanel.channel_unified(
sub,
context,
brush,
"dyntopo_mode",
text="Refine Method",
expand=True,
ui_editing=False
)
#"""
if detail_mode in {'CONSTANT', 'MANUAL'}:
col.operator("sculpt.detail_flood_fill")
col.prop(sculpt, "use_dyntopo_cleanup")
#col.prop(sculpt, "use_dyntopo_cleanup")
col.prop(sculpt, "use_smooth_shading")
col.prop(sculpt, "use_flat_vcol_shading")
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_spacing", slider=True)
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_radius_scale", slider=True)
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_spacing", slider=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(layout, context, brush, "dyntopo_radius_scale", slider=True, ui_editing=False)
#col.prop(sculpt, "dyntopo_spacing")
#col.prop(sculpt, "dyntopo_radius_scale");
@ -1015,13 +1169,19 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
layout.column(),
context,
brush,
"automasking", toolsettings_only=True)
"automasking", toolsettings_only=True, expand=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(
layout.column(),
context,
brush,
"automasking_boundary_edges_propagation_steps",
toolsettings_only=True)
toolsettings_only=True, ui_editing=False)
UnifiedPaintPanel.channel_unified(
layout.column(),
context,
brush,
"concave_mask_factor",
toolsettings_only=True, ui_editing=False, slider=True)
"""
col = layout.column(heading="Auto-Masking", align=True)
@ -2441,7 +2601,8 @@ classes = (
VIEW3D_PT_tools_grease_pencil_brush_vertex_color,
VIEW3D_PT_tools_grease_pencil_brush_vertex_palette,
VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff,
VIEW3D_PT_sculpt_dyntopo_advanced
VIEW3D_PT_sculpt_dyntopo_advanced,
SCULPT_OT_set_dyntopo_mode
)
if __name__ == "__main__": # only for live edit.

View File

@ -119,17 +119,22 @@ void BKE_brush_size_set(struct Scene *scene,
int size,
bool use_brush_channel);
float BKE_brush_unprojected_radius_get(const struct Scene *scene, const struct Brush *brush);
float BKE_brush_unprojected_radius_get(const struct Scene *scene,
const struct Brush *brush,
bool use_channels);
void BKE_brush_unprojected_radius_set(struct Scene *scene,
struct Brush *brush,
float unprojected_radius);
float unprojected_radius,
bool use_channels);
float BKE_brush_alpha_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_alpha_set(struct Scene *scene, struct Brush *brush, float alpha);
float BKE_brush_weight_get(const struct Scene *scene, const struct Brush *brush);
void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float value);
bool BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush);
bool BKE_brush_use_locked_size(const struct Scene *scene,
const struct Brush *brush,
bool use_channels);
bool BKE_brush_use_alpha_pressure(const struct Brush *brush);
bool BKE_brush_use_size_pressure(const struct Brush *brush);

View File

@ -63,6 +63,8 @@ struct Sculpt;
BKE_brush_channelset_lookup(chset, MAKE_BUILTIN_CH_NAME(channel))
#define BRUSHSET_GET_FLOAT(chset, channel, mapdata) \
BKE_brush_channelset_get_float(chset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_FINAL_FLOAT(childset, parentset, channel, mapdata) \
BKE_brush_channelset_get_final_float(childset, parentset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_INT(chset, channel, mapdata) \
BKE_brush_channelset_get_int(chset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_ENSURE_BUILTIN(chset, channel) \
@ -287,6 +289,7 @@ bool BKE_brush_mapping_ensure_write(BrushMapping *mp);
void BKE_brush_channelset_apply_mapping(BrushChannelSet *chset, BrushMappingData *mapdata);
void BKE_brush_check_toolsettings(struct Sculpt *sd);
void BKE_brush_channelset_ui_init(struct Brush *brush, int tool);
void BKE_brush_channelset_check_radius(BrushChannelSet *chset);
/*
set up static type checker for BRUSHSET_XXX macros

View File

@ -226,7 +226,7 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_texture_mtex_foreach_id(data, &brush->mask_mtex);
}
ATTR_NO_OPT static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Brush *brush = (Brush *)id;
@ -2517,12 +2517,24 @@ int BKE_brush_size_get(const Scene *scene, const Brush *brush, bool use_brush_ch
return size;
}
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush, bool use_brush_channels)
{
const short us_flag = scene->toolsettings->unified_paint_settings.flag;
if (use_brush_channels) {
Sculpt *sd = scene->toolsettings->sculpt;
if (sd) {
return BKE_brush_channelset_get_final_int(
brush->channels, sd->channels, "radius_unit", NULL);
}
else {
return BKE_brush_channelset_get_int(brush->channels, "radius_unit", NULL);
}
}
else {
const short us_flag = scene->toolsettings->unified_paint_settings.flag;
return (us_flag & UNIFIED_PAINT_SIZE) ? (us_flag & UNIFIED_PAINT_BRUSH_LOCK_SIZE) :
(brush->flag & BRUSH_LOCK_SIZE);
return (us_flag & UNIFIED_PAINT_SIZE) ? (us_flag & UNIFIED_PAINT_BRUSH_LOCK_SIZE) :
(brush->flag & BRUSH_LOCK_SIZE);
}
}
bool BKE_brush_use_size_pressure(const Brush *brush)
@ -2554,10 +2566,40 @@ bool BKE_brush_sculpt_has_secondary_color(const Brush *brush)
SCULPT_TOOL_MASK);
}
void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojected_radius)
void BKE_brush_unprojected_radius_set(Scene *scene,
Brush *brush,
float unprojected_radius,
bool use_channels)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
if (use_channels) {
BrushChannel *ch1 = BRUSHSET_LOOKUP(brush->channels, unprojected_radius);
BrushChannel *ch2 = NULL;
if (scene->toolsettings && scene->toolsettings->sculpt &&
scene->toolsettings->sculpt->channels) {
ch2 = BRUSHSET_LOOKUP(scene->toolsettings->sculpt->channels, unprojected_radius);
}
if (ch1 && ch2) {
if (ch1->flag & BRUSH_CHANNEL_INHERIT) {
ch2->fvalue = unprojected_radius;
}
else {
ch1->fvalue = unprojected_radius;
}
}
else if (ch1) {
ch1->fvalue = unprojected_radius;
}
else if (ch2) {
ch2->fvalue = unprojected_radius;
}
return;
}
if (ups->flag & UNIFIED_PAINT_SIZE) {
ups->unprojected_radius = unprojected_radius;
}
@ -2566,8 +2608,23 @@ void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojec
}
}
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush, bool use_channels)
{
if (use_channels) {
BrushChannelSet *chset = NULL;
if (scene->toolsettings && scene->toolsettings->sculpt) {
chset = scene->toolsettings->sculpt->channels;
}
if (chset) {
return BRUSHSET_GET_FINAL_FLOAT(brush->channels, chset, unprojected_radius, NULL);
}
else {
return BRUSHSET_GET_FLOAT(brush->channels, unprojected_radius, NULL);
}
}
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return (ups->flag & UNIFIED_PAINT_SIZE) ? ups->unprojected_radius : brush->unprojected_radius;
@ -2675,10 +2732,10 @@ void BKE_brush_randomize_texture_coords(UnifiedPaintSettings *ups, bool mask)
}
}
ATTR_NO_OPT float BKE_brush_curve_strength_ex(int curve_preset,
const CurveMapping *curve,
float p,
const float len)
float BKE_brush_curve_strength_ex(int curve_preset,
const CurveMapping *curve,
float p,
const float len)
{
float strength = 1.0f;
@ -2726,7 +2783,7 @@ ATTR_NO_OPT float BKE_brush_curve_strength_ex(int curve_preset,
}
/* Uses the brush curve control to find a strength value */
ATTR_NO_OPT float BKE_brush_curve_strength(const Brush *br, float p, const float len)
float BKE_brush_curve_strength(const Brush *br, float p, const float len)
{
return BKE_brush_curve_strength_ex(br->curve_preset, br->curve, p, len);
}

View File

@ -136,8 +136,8 @@ places in rna_engine_codebase are relevent:
MAKE_FLAGS_EX(automasking, "Automasking", "", 0, _({
{BRUSH_AUTOMASKING_BOUNDARY_EDGES, "BOUNDARY_EDGE", ICON_NONE, "Boundary Edges", ""},
{BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS, "BOUNDARY_FACE_SETS", ICON_NONE, "Boundary Face Sets", ""},
{BRUSH_AUTOMASKING_CONCAVITY, "CONCAVITY", ICON_NONE, "Concave", ""},
{BRUSH_AUTOMASKING_INVERT_CONCAVITY, "INVERT_CONCAVITY", ICON_NONE, "Invert Concave", "Invert Concave Map"},
{BRUSH_AUTOMASKING_CONCAVITY, "CONCAVITY", ICON_NONE, "Cavity", ""},
{BRUSH_AUTOMASKING_INVERT_CONCAVITY, "INVERT_CONCAVITY", ICON_NONE, "Invert Cavity", "Invert Cavity Map"},
{BRUSH_AUTOMASKING_FACE_SETS, "FACE_SETS", ICON_NONE, "Face Sets", ""},
{BRUSH_AUTOMASKING_TOPOLOGY, "TOPOLOGY", ICON_NONE, "Topology", ""},
{-1},
@ -195,6 +195,14 @@ MAKE_FLOAT_EX_FLAG(dyntopo_detail_range, "Detail Range", "Detail Range", 0.45f,
MAKE_FLOAT_EX_FLAG(dyntopo_detail_size, "Detail Size", "Detail Size", 8.0f, 0.1f, 100.0f, 0.001f, 500.0f, false, BRUSH_CHANNEL_INHERIT)
MAKE_FLOAT_EX_FLAG(dyntopo_constant_detail, "Constaint Detail", "", 3.0f, 0.001f, 1000.0f, 0.0001, FLT_MAX, false, BRUSH_CHANNEL_INHERIT)
MAKE_FLOAT_EX_FLAG(dyntopo_spacing, "Spacing", "Dyntopo Spacing", 35.0f, 0.01f, 300.0f, 0.001f, 50000.0f, false, BRUSH_CHANNEL_INHERIT)
MAKE_ENUM_EX(dyntopo_detail_mode, "Detail Mode", "", DYNTOPO_DETAIL_RELATIVE, _({
{DYNTOPO_DETAIL_RELATIVE, "RELATIVE", "NONE", "Relative", ""},
{DYNTOPO_DETAIL_CONSTANT, "CONSTANT", "NONE", "Constant", ""},
{DYNTOPO_DETAIL_MANUAL, "MANUAL", "NONE", "Manual", ""},
{DYNTOPO_DETAIL_BRUSH, "BRUSH", "NONE", "Brush", ""},
{-1}
}), BRUSH_CHANNEL_INHERIT)
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 "
@ -327,6 +335,12 @@ MAKE_ENUM(deform_target, "Deformation Target", "How the deformation of the brush
MAKE_CURVE(autosmooth_falloff_curve, "Falloff", "Custom curve for autosmooth", BRUSH_CURVE_SMOOTH)
MAKE_CURVE(topology_rake_falloff_curve, "Falloff", "Custom curve for topolgoy rake", BRUSH_CURVE_SMOOTH)
MAKE_CURVE(falloff_curve, "Falloff", "Falloff curve", BRUSH_CURVE_SMOOTH)
MAKE_FLOAT_EX(unprojected_radius, "Unprojected Radius", "Radius of brush in Blender units", 0.1f, 0.001, FLT_MAX, 0.001, 1.0f, false)
MAKE_ENUM_EX(radius_unit, "Radius Unit", "Measure brush size relative to the view or the scene", 0, _({
{0, "VIEW", "NONE", "View", "Measure brush size relative to the view"},
{BRUSH_LOCK_SIZE, "SCENE", "NONE", "Scene", "Measure brush size relative to the scene"},
{-1}
}), BRUSH_CHANNEL_SHOW_IN_WORKSPACE)
/* clang-format on */
#if defined(BRUSH_CHANNEL_DEFINE_TYPES) || defined(BRUSH_CHANNEL_DEFINE_EXTERNAL)
@ -373,7 +387,9 @@ MAKE_CURVE(falloff_curve, "Falloff", "Falloff curve", BRUSH_CURVE_SMOOTH)
# ifdef MAKE_FLAGS_EX
# undef MAKE_FLAGS_EX
# endif
# ifdef MAKE_FLOAT_EX_FLAG
# undef MAKE_FLOAT_EX_FLAG
# endif
# ifdef MAKE_BUILTIN_CH_DEF
# undef MAKE_BUILTIN_CH_DEF
# endif

View File

@ -129,7 +129,7 @@ bool BKE_brush_channel_curve_ensure_write(BrushCurve *curve)
return false;
}
ATTR_NO_OPT static bool check_corrupted_curve(BrushMapping *dst)
static bool check_corrupted_curve(BrushMapping *dst)
{
CurveMapping *curve = dst->curve;
@ -175,8 +175,8 @@ generated from the node group inputs.
extern BrushChannelType brush_builtin_channels[];
extern const int brush_builtin_channel_len;
ATTR_NO_OPT void BKE_brush_channeltype_rna_check(BrushChannelType *def,
int (*getIconFromName)(const char *name))
void BKE_brush_channeltype_rna_check(BrushChannelType *def,
int (*getIconFromName)(const char *name))
{
if (def->rna_enumdef) {
return;
@ -210,7 +210,7 @@ ATTR_NO_OPT void BKE_brush_channeltype_rna_check(BrushChannelType *def,
}
}
ATTR_NO_OPT void BKE_brush_channel_free_data(BrushChannel *ch)
void BKE_brush_channel_free_data(BrushChannel *ch)
{
if (ch->curve.curve) {
RELEASE_OR_FREE_CURVE(ch->curve.curve);
@ -223,13 +223,13 @@ ATTR_NO_OPT void BKE_brush_channel_free_data(BrushChannel *ch)
}
}
ATTR_NO_OPT void BKE_brush_channel_free(BrushChannel *ch)
void BKE_brush_channel_free(BrushChannel *ch)
{
BKE_brush_channel_free_data(ch);
MEM_freeN(ch);
}
ATTR_NO_OPT static void copy_channel_data_keep_mappings(BrushChannel *dst, BrushChannel *src)
static void copy_channel_data_keep_mappings(BrushChannel *dst, BrushChannel *src)
{
BLI_strncpy(dst->name, src->name, sizeof(dst->name));
BLI_strncpy(dst->idname, src->idname, sizeof(dst->idname));
@ -277,9 +277,7 @@ ATTR_NO_OPT static void copy_channel_data_keep_mappings(BrushChannel *dst, Brush
}
}
ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst,
BrushChannel *src,
bool keep_mapping)
void BKE_brush_channel_copy_data(BrushChannel *dst, BrushChannel *src, bool keep_mapping)
{
if (keep_mapping) {
copy_channel_data_keep_mappings(dst, src);
@ -345,7 +343,7 @@ ATTR_NO_OPT void BKE_brush_channel_copy_data(BrushChannel *dst,
namestack_pop(NULL);
}
ATTR_NO_OPT void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
{
// preserve linked list pointers
BrushChannel *next = ch->next, *prev = ch->prev;
@ -453,7 +451,7 @@ BrushChannelSet *BKE_brush_channelset_create()
return chset;
}
ATTR_NO_OPT void BKE_brush_channelset_free(BrushChannelSet *chset)
void BKE_brush_channelset_free(BrushChannelSet *chset)
{
BrushChannel *ch, *next;
@ -470,7 +468,7 @@ ATTR_NO_OPT void BKE_brush_channelset_free(BrushChannelSet *chset)
static int _rng_seed = 0;
ATTR_NO_OPT void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch)
void BKE_brush_channel_ensure_unque_name(BrushChannelSet *chset, BrushChannel *ch)
{
BrushChannel *ch2;
int i = 1;
@ -529,9 +527,7 @@ void BKE_brush_channelset_add(BrushChannelSet *chset, BrushChannel *ch)
chset->totchannel++;
}
ATTR_NO_OPT void BKE_brush_channel_rename(BrushChannelSet *chset,
BrushChannel *ch,
const char *newname)
void BKE_brush_channel_rename(BrushChannelSet *chset, BrushChannel *ch, const char *newname)
{
BLI_ghash_remove(chset->namemap, ch->idname, NULL, NULL);
BLI_strncpy(ch->idname, newname, sizeof(ch->idname));
@ -539,7 +535,7 @@ ATTR_NO_OPT void BKE_brush_channel_rename(BrushChannelSet *chset,
BLI_ghash_insert(chset->namemap, ch->idname, ch);
}
ATTR_NO_OPT void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch)
void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChannel *ch)
{
BLI_ghash_remove(chset->namemap, ch->idname, NULL, NULL);
BLI_remlink(&chset->channels, ch);
@ -547,7 +543,7 @@ ATTR_NO_OPT void BKE_brush_channelset_remove(BrushChannelSet *chset, BrushChanne
chset->totchannel--;
}
ATTR_NO_OPT bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname)
bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const char *idname)
{
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
if (ch) {
@ -558,7 +554,7 @@ ATTR_NO_OPT bool BKE_brush_channelset_remove_named(BrushChannelSet *chset, const
return false;
}
ATTR_NO_OPT void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch)
void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, BrushChannel *ch)
{
namestack_push(__func__);
@ -574,12 +570,12 @@ ATTR_NO_OPT void BKE_brush_channelset_add_duplicate(BrushChannelSet *chset, Brus
namestack_pop(NULL);
}
ATTR_NO_OPT BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname)
BrushChannel *BKE_brush_channelset_lookup(BrushChannelSet *chset, const char *idname)
{
return BLI_ghash_lookup(chset->namemap, idname);
}
ATTR_NO_OPT bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname)
bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname)
{
return BKE_brush_channelset_lookup(chset, idname) != NULL;
}
@ -605,12 +601,12 @@ BrushChannelType *BKE_brush_default_channel_def()
return &brush_default_channel_type;
}
ATTR_NO_OPT void BKE_brush_channel_def_copy(BrushChannelType *dst, BrushChannelType *src)
void BKE_brush_channel_def_copy(BrushChannelType *dst, BrushChannelType *src)
{
memcpy(dst, src, sizeof(*dst));
}
ATTR_NO_OPT BrushChannelType *BKE_brush_builtin_channel_def_find(const char *name)
BrushChannelType *BKE_brush_builtin_channel_def_find(const char *name)
{
for (int i = 0; i < brush_builtin_channel_len; i++) {
BrushChannelType *def = brush_builtin_channels + i;
@ -623,8 +619,7 @@ ATTR_NO_OPT BrushChannelType *BKE_brush_builtin_channel_def_find(const char *nam
return NULL;
}
ATTR_NO_OPT BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset,
const char *idname)
BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname)
{
BrushChannelType *def = BKE_brush_builtin_channel_def_find(idname);
@ -662,8 +657,7 @@ BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const
return ch;
}
ATTR_NO_OPT void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset,
BrushChannel *existing)
void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset, BrushChannel *existing)
{
if (BKE_brush_channelset_has(chset, existing->idname)) {
return;
@ -674,9 +668,9 @@ ATTR_NO_OPT void BKE_brush_channelset_ensure_existing(BrushChannelSet *chset,
namestack_pop(NULL);
}
ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent)
void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent)
{
// first add missing channels
namestack_push(__func__);
@ -738,9 +732,9 @@ ATTR_NO_OPT void BKE_brush_channelset_merge(BrushChannelSet *dst,
}
#ifdef DEBUG_CURVE_MAPPING_ALLOC
ATTR_NO_OPT BrushChannelSet *_BKE_brush_channelset_copy(BrushChannelSet *src)
BrushChannelSet *_BKE_brush_channelset_copy(BrushChannelSet *src)
#else
ATTR_NO_OPT BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src)
BrushChannelSet *BKE_brush_channelset_copy(BrushChannelSet *src)
#endif
{
BrushChannelSet *chset = BKE_brush_channelset_create();
@ -999,7 +993,7 @@ float BKE_brush_channelset_get_float(BrushChannelSet *chset,
return BKE_brush_channel_get_float(ch, mapdata);
}
ATTR_NO_OPT float BKE_brush_channel_get_float(BrushChannel *ch, BrushMappingData *mapdata)
float BKE_brush_channel_get_float(BrushChannel *ch, BrushMappingData *mapdata)
{
float f = ch->fvalue;
@ -1051,7 +1045,7 @@ ATTR_NO_OPT float BKE_brush_channel_get_float(BrushChannel *ch, BrushMappingData
return f;
}
ATTR_NO_OPT void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4])
void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4])
{
if (ch->type == BRUSH_CHANNEL_VEC4) {
copy_v4_v4(ch->vector, vec);
@ -1061,7 +1055,7 @@ ATTR_NO_OPT void BKE_brush_channel_set_vector(BrushChannel *ch, float vec[4])
}
}
ATTR_NO_OPT int BKE_brush_channel_get_vector_size(BrushChannel *ch)
int BKE_brush_channel_get_vector_size(BrushChannel *ch)
{
switch (ch->type) {
case BRUSH_CHANNEL_VEC3:
@ -1073,9 +1067,7 @@ ATTR_NO_OPT int BKE_brush_channel_get_vector_size(BrushChannel *ch)
}
}
ATTR_NO_OPT int BKE_brush_channel_get_vector(BrushChannel *ch,
float out[4],
BrushMappingData *mapdata)
int BKE_brush_channel_get_vector(BrushChannel *ch, float out[4], BrushMappingData *mapdata)
{
int size = 3;
if (ch->type == BRUSH_CHANNEL_VEC4) {
@ -1240,7 +1232,7 @@ bool BKE_brush_channelset_set_float(BrushChannelSet *chset, const char *idname,
return true;
}
ATTR_NO_OPT bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val)
bool BKE_brush_channelset_set_int(BrushChannelSet *chset, const char *idname, int val)
{
BrushChannel *ch = BKE_brush_channelset_lookup(chset, idname);
@ -1403,7 +1395,7 @@ static void _float_set_uninherit(BrushChannelSet *chset, const char *channel, fl
/*flag all mappings to use inherited curves even if owning channel
is not set to inherit.*/
ATTR_NO_OPT void BKE_brush_commandset_inherit_all_mappings(BrushChannelSet *chset)
void BKE_brush_commandset_inherit_all_mappings(BrushChannelSet *chset)
{
BrushChannel *ch;
for (ch = chset->channels.first; ch; ch = ch->next) {
@ -1413,11 +1405,11 @@ ATTR_NO_OPT void BKE_brush_commandset_inherit_all_mappings(BrushChannelSet *chse
}
}
ATTR_NO_OPT static void bke_builtin_commandlist_create_paint(Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *mapdata)
static void bke_builtin_commandlist_create_paint(Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *mapdata)
{
BrushCommand *cmd;
@ -1478,11 +1470,11 @@ ATTR_NO_OPT static void bke_builtin_commandlist_create_paint(Brush *brush,
// float
}
ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *mapdata)
void BKE_builtin_commandlist_create(Brush *brush,
BrushChannelSet *chset,
BrushCommandList *cl,
int tool,
BrushMappingData *mapdata)
{
BrushCommand *cmd;
BrushChannel *ch;
@ -1604,7 +1596,7 @@ ATTR_NO_OPT void BKE_builtin_commandlist_create(Brush *brush,
BKE_brush_commandset_inherit_all_mappings(cmd->params);
}
ATTR_NO_OPT void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
{
BLO_read_list(reader, &chset->channels);
@ -1668,7 +1660,7 @@ ATTR_NO_OPT void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannel
}
}
ATTR_NO_OPT void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *chset)
void BKE_brush_channelset_write(BlendWriter *writer, BrushChannelSet *chset)
{
BLO_write_struct(writer, BrushChannelSet, chset);
BLO_write_struct_list(writer, BrushChannel, &chset->channels);

View File

@ -180,7 +180,7 @@ BrushChannelType brush_builtin_channels[] = {
const int brush_builtin_channel_len = ARRAY_SIZE(brush_builtin_channels);
static bool do_builtin_init = true;
ATTR_NO_OPT static bool check_builtin_init()
static bool check_builtin_init()
{
if (!do_builtin_init || !BLI_thread_is_main()) {
return false;
@ -219,11 +219,14 @@ ATTR_NO_OPT static bool check_builtin_init()
# undef GETCH
#endif
/* TODO: replace these two macros with equivalent BRUSHSET_XXX ones */
#define ADDCH(name) \
(BKE_brush_channelset_ensure_builtin(chset, BRUSH_BUILTIN_##name), \
BKE_brush_channelset_lookup(chset, BRUSH_BUILTIN_##name))
#define GETCH(name) BKE_brush_channelset_lookup(chset, BRUSH_BUILTIN_##name)
/* create pointer map between brush channels and old brush settings */
/* clang-format off */
#define DEF(brush_member, channel_name, btype, ctype) \
{offsetof(Brush, brush_member), #channel_name, btype, ctype, sizeof(((Brush){0}).brush_member)},
@ -307,7 +310,9 @@ static BrushSettingsMap dyntopo_settings_map[] = {
DEF(constant_detail, dyntopo_constant_detail, FLOAT, FLOAT)
DEF(spacing, dyntopo_spacing, INT, FLOAT)
DEF(radius_scale, dyntopo_radius_scale, FLOAT, FLOAT)
DEF(mode, dyntopo_detail_mode, INT, INT)
};
static const int dyntopo_settings_map_len = ARRAY_SIZE(dyntopo_settings_map);
/* clang-format on */
@ -345,14 +350,14 @@ BrushFlagMap brush_flags_map[] = {
DEF(flag, use_frontface, BRUSH_FRONTFACE)
DEF(flag2, cloth_use_collision, BRUSH_CLOTH_USE_COLLISION)
DEF(flag2, cloth_pin_simulation_boundary, BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY)
DEF(flag, radius_unit, BRUSH_LOCK_SIZE)
};
int brush_flags_map_len = ARRAY_SIZE(brush_flags_map);
/* clang-format on */
static ATTR_NO_OPT void do_coerce(
int type1, void *ptr1, int size1, int type2, void *ptr2, int size2)
static void do_coerce(int type1, void *ptr1, int size1, int type2, void *ptr2, int size2)
{
double val = 0;
float vec[4];
@ -444,7 +449,7 @@ void *get_channel_value_pointer(BrushChannel *ch, int *r_data_size)
return NULL;
}
ATTR_NO_OPT static void brush_flags_from_channels(BrushChannelSet *chset, Brush *brush)
static void brush_flags_from_channels(BrushChannelSet *chset, Brush *brush)
{
for (int i = 0; i < brush_flags_map_len; i++) {
BrushFlagMap *mf = brush_flags_map + i;
@ -502,7 +507,7 @@ ATTR_NO_OPT static void brush_flags_from_channels(BrushChannelSet *chset, Brush
}
}
ATTR_NO_OPT static void brush_flags_to_channels(BrushChannelSet *chset, Brush *brush)
static void brush_flags_to_channels(BrushChannelSet *chset, Brush *brush)
{
for (int i = 0; i < brush_flags_map_len; i++) {
BrushFlagMap *mf = brush_flags_map + i;
@ -540,11 +545,11 @@ ATTR_NO_OPT static void brush_flags_to_channels(BrushChannelSet *chset, Brush *b
}
}
ATTR_NO_OPT void BKE_brush_channelset_compat_load_intern(BrushChannelSet *chset,
void *data,
bool brush_to_channels,
BrushSettingsMap *settings_map,
int settings_map_len)
void BKE_brush_channelset_compat_load_intern(BrushChannelSet *chset,
void *data,
bool brush_to_channels,
BrushSettingsMap *settings_map,
int settings_map_len)
{
for (int i = 0; i < settings_map_len; i++) {
BrushSettingsMap *mp = settings_map + i;
@ -569,9 +574,7 @@ ATTR_NO_OPT void BKE_brush_channelset_compat_load_intern(BrushChannelSet *chset,
}
}
ATTR_NO_OPT void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
Brush *brush,
bool brush_to_channels)
void BKE_brush_channelset_compat_load(BrushChannelSet *chset, Brush *brush, bool brush_to_channels)
{
if (brush_to_channels) {
brush_flags_to_channels(chset, brush);
@ -609,12 +612,6 @@ ATTR_NO_OPT void BKE_brush_channelset_compat_load(BrushChannelSet *chset,
BKE_brush_channelset_set_int(chset, "dyntopo_mode", brush->dyntopo.flag & mask);
BKE_brush_channelset_set_int(
chset, "dyntopo_disabled", brush->dyntopo.flag & DYNTOPO_DISABLED ? 1 : 0);
BRUSHSET_SET_FLOAT(chset, dyntopo_detail_range, brush->dyntopo.detail_range);
BRUSHSET_SET_FLOAT(chset, dyntopo_detail_percent, brush->dyntopo.detail_percent);
BRUSHSET_SET_FLOAT(chset, dyntopo_detail_size, brush->dyntopo.detail_size);
BRUSHSET_SET_FLOAT(chset, dyntopo_constant_detail, brush->dyntopo.constant_detail);
BRUSHSET_SET_FLOAT(chset, dyntopo_spacing, brush->dyntopo.spacing);
}
/* pen pressure flags */
@ -723,6 +720,8 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(radius);
ADDCH(spacing);
ADDCH(strength);
ADDCH(radius_unit);
ADDCH(unprojected_radius);
ADDCH(autosmooth);
ADDCH(autosmooth_radius_scale);
@ -751,7 +750,9 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(automasking);
ADDCH(automasking_boundary_edges_propagation_steps);
ADDCH(concave_mask_factor);
ADDCH(dyntopo_disabled);
ADDCH(dyntopo_detail_mode)->flag |= BRUSH_CHANNEL_INHERIT;
ADDCH(dyntopo_mode)->flag |= BRUSH_CHANNEL_INHERIT;
ADDCH(dyntopo_detail_range)->flag |= BRUSH_CHANNEL_INHERIT;
ADDCH(dyntopo_detail_percent)->flag |= BRUSH_CHANNEL_INHERIT;
@ -827,7 +828,7 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
namestack_pop();
}
ATTR_NO_OPT void BKE_brush_channelset_ui_init(Brush *brush, int tool)
void BKE_brush_channelset_ui_init(Brush *brush, int tool)
{
namestack_push(__func__);
@ -864,6 +865,7 @@ ATTR_NO_OPT void BKE_brush_channelset_ui_init(Brush *brush, int tool)
SHOWALL(secondary_color);
SHOWALL(accumulate);
SHOWWRK(radius_unit);
SHOWWRK(use_frontface);
SHOWWRK(autosmooth);
@ -920,7 +922,7 @@ ATTR_NO_OPT void BKE_brush_channelset_ui_init(Brush *brush, int tool)
#undef SHOWPROPS
namestack_pop();
}
ATTR_NO_OPT void BKE_brush_builtin_create(Brush *brush, int tool)
void BKE_brush_builtin_create(Brush *brush, int tool)
{
namestack_push(__func__);
@ -938,17 +940,25 @@ ATTR_NO_OPT void BKE_brush_builtin_create(Brush *brush, int tool)
ADDCH(area_radius_factor);
switch (tool) {
case SCULPT_TOOL_DRAW: {
case SCULPT_TOOL_DRAW:
break;
case SCULPT_TOOL_SIMPLIFY: {
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, radius)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_SET_FLOAT(chset, strength, 0.5);
BRUSHSET_SET_FLOAT(chset, autosmooth, 0.05);
BRUSHSET_SET_INT(chset, topology_rake_mode, 1); // curvature mode
BRUSHSET_SET_FLOAT(chset, topology_rake, 0.35);
BrushChannel *ch = BRUSHSET_LOOKUP(chset, dyntopo_mode);
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
ch->flag |= BRUSH_CHANNEL_INHERIT_IF_UNSET;
break;
}
case SCULPT_TOOL_SIMPLIFY:
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
GETCH(strength)->fvalue = 0.5;
GETCH(autosmooth)->fvalue = 0.05;
GETCH(topology_rake_mode)->ivalue = 1; // curvature mode
GETCH(topology_rake)->fvalue = 0.35;
break;
case SCULPT_TOOL_DRAW_SHARP:
GETCH(spacing)->ivalue = 5;
GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
@ -1048,6 +1058,7 @@ ATTR_NO_OPT void BKE_brush_builtin_create(Brush *brush, int tool)
namestack_pop();
BKE_brush_channelset_ui_init(brush, tool);
BKE_brush_channelset_check_radius(chset);
}
void BKE_brush_init_toolsettings(Sculpt *sd)
@ -1059,10 +1070,42 @@ void BKE_brush_init_toolsettings(Sculpt *sd)
}
BKE_brush_check_toolsettings(sd);
BKE_brush_channelset_check_radius(sd->channels);
namestack_pop();
}
// syncs radius and unprojected_radius's flags
void BKE_brush_channelset_check_radius(BrushChannelSet *chset)
{
BrushChannel *ch1 = BRUSHSET_LOOKUP(chset, radius);
BrushChannel *ch2 = BRUSHSET_LOOKUP(chset, unprojected_radius);
if (!ch2) {
return;
}
int mask = BRUSH_CHANNEL_INHERIT | BRUSH_CHANNEL_INHERIT_IF_UNSET |
BRUSH_CHANNEL_SHOW_IN_HEADER | BRUSH_CHANNEL_SHOW_IN_WORKSPACE |
BRUSH_CHANNEL_UI_EXPANDED;
if (ch2) {
ch2->flag &= ~mask;
ch2->flag |= mask & ch1->flag;
}
mask = BRUSH_MAPPING_ENABLED | BRUSH_MAPPING_INHERIT | BRUSH_MAPPING_INVERT |
BRUSH_MAPPING_UI_EXPANDED;
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
BrushMapping *mp1 = ch1->mappings + i;
BrushMapping *mp2 = ch2->mappings + i;
mp2->flag &= ~mask;
mp2->flag |= mp1->flag & mask;
}
}
void BKE_brush_check_toolsettings(Sculpt *sd)
{
namestack_push(__func__);
@ -1071,6 +1114,9 @@ void BKE_brush_check_toolsettings(Sculpt *sd)
ADDCH(radius);
ADDCH(strength);
ADDCH(radius_unit);
ADDCH(unprojected_radius);
ADDCH(automasking_boundary_edges_propagation_steps);
ADDCH(concave_mask_factor);
ADDCH(automasking);
@ -1099,6 +1145,7 @@ void BKE_brush_check_toolsettings(Sculpt *sd)
ADDCH(color);
ADDCH(secondary_color);
ADDCH(dyntopo_detail_mode);
ADDCH(dyntopo_disabled);
ADDCH(dyntopo_mode);
ADDCH(dyntopo_detail_range);

View File

@ -85,8 +85,7 @@ void BKE_curvemapping_set_defaults(
cumap->changed_timestamp = 0;
}
ATTR_NO_OPT CurveMapping *BKE_curvemapping_add(
int tot, float minx, float miny, float maxx, float maxy)
CurveMapping *BKE_curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
{
CurveMapping *cumap;
@ -97,7 +96,7 @@ ATTR_NO_OPT CurveMapping *BKE_curvemapping_add(
return cumap;
}
ATTR_NO_OPT void BKE_curvemapping_free_data(CurveMapping *cumap)
void BKE_curvemapping_free_data(CurveMapping *cumap)
{
int a;
@ -189,7 +188,7 @@ void BKE_curvemapping_copy_data(CurveMapping *target, const CurveMapping *cumap)
}
}
ATTR_NO_OPT CurveMapping *BKE_curvemapping_copy(const CurveMapping *cumap)
CurveMapping *BKE_curvemapping_copy(const CurveMapping *cumap)
{
if (cumap) {
CurveMapping *cumapn = MEM_dupallocN(cumap);
@ -1349,8 +1348,7 @@ void BKE_curvemapping_blend_write(BlendWriter *writer, const CurveMapping *cumap
BKE_curvemapping_curves_blend_write(writer, cumap);
}
ATTR_NO_OPT void BKE_curvemapping_curves_blend_write(BlendWriter *writer,
const CurveMapping *cumap)
void BKE_curvemapping_curves_blend_write(BlendWriter *writer, const CurveMapping *cumap)
{
for (int a = 0; a < CM_TOT; a++) {
BLO_write_struct_array(writer, CurveMapPoint, cumap->cm[a].totpoint, cumap->cm[a].curve);

View File

@ -62,7 +62,7 @@ static int curvmapping_curve_count(const CurveMapping *cumap)
return count;
}
ATTR_NO_OPT bool BKE_curvemapping_equals(const CurveMapping *a, const CurveMapping *b)
bool BKE_curvemapping_equals(const CurveMapping *a, const CurveMapping *b)
{
int count = curvmapping_curve_count(a);
@ -112,7 +112,7 @@ ATTR_NO_OPT bool BKE_curvemapping_equals(const CurveMapping *a, const CurveMappi
/*truncate float to avoid rounding errors
messing up the hash*/
#define FRACT_TRUNCATE_STEPS 8192.0f
ATTR_NO_OPT BLI_INLINE unsigned int get_float_hash(float f)
BLI_INLINE unsigned int get_float_hash(float f)
{
float f_floor = floor(f);
float fract = f - f_floor;
@ -126,7 +126,7 @@ ATTR_NO_OPT BLI_INLINE unsigned int get_float_hash(float f)
#define HASHFLOAT(f) h = get_float_hash(f), hash ^= BLI_hash_int(h + hi++)
#define HASHINT(f) h = get_float_hash(f), hash ^= BLI_hash_int(f + hi++)
ATTR_NO_OPT uint BKE_curvemapping_calc_hash(const CurveMapping *cumap)
uint BKE_curvemapping_calc_hash(const CurveMapping *cumap)
{
uint hash = 0;
uint h = 0;
@ -184,7 +184,7 @@ void BKE_curvemapping_cache_aquire(CurveMappingCache *cache, CurveMapping *curve
curve->cache_users++;
}
ATTR_NO_OPT void BKE_curvemapping_cache_release(CurveMappingCache *cache, CurveMapping *curve)
void BKE_curvemapping_cache_release(CurveMappingCache *cache, CurveMapping *curve)
{
curve->cache_users--;
@ -202,9 +202,9 @@ bool BKE_curvemapping_in_cache(CurveMapping *curve)
return curve->flag & CUMA_PART_OF_CACHE;
}
ATTR_NO_OPT CurveMapping *BKE_curvemapping_cache_get(CurveMappingCache *cache,
CurveMapping *curve,
bool free_input)
CurveMapping *BKE_curvemapping_cache_get(CurveMappingCache *cache,
CurveMapping *curve,
bool free_input)
{
void **key, **val;
@ -284,8 +284,7 @@ CurveMappingCache *BKE_curvemapping_cache_global()
}
// releases a curve if it's in the cache, otherwise frees it
ATTR_NO_OPT void BKE_curvemapping_cache_release_or_free(CurveMappingCache *cache,
CurveMapping *curve)
void BKE_curvemapping_cache_release_or_free(CurveMappingCache *cache, CurveMapping *curve)
{
if (curve->flag & CUMA_PART_OF_CACHE) {
BKE_curvemapping_cache_release(cache, curve);

View File

@ -2651,6 +2651,7 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.use_threading = false;
BLI_task_parallel_range(0, count, tdata, long_edge_queue_task_cb, &settings);
const int cd_dyn_vert = pbvh->cd_dyn_vert;

View File

@ -35,9 +35,9 @@
#include "BLI_index_range.hh"
#include "BLI_span.hh"
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BKE_bvhutils.h"
#include "BKE_customdata.h"
@ -68,14 +68,14 @@ using blender::MutableSpan;
using blender::Span;
#ifdef WITH_QUADRIFLOW
ATTR_NO_OPT static Mesh *remesh_quadriflow(const Mesh *input_mesh,
int target_faces,
int seed,
bool preserve_sharp,
bool preserve_boundary,
bool adaptive_scale,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
static Mesh *remesh_quadriflow(const Mesh *input_mesh,
int target_faces,
int seed,
bool preserve_sharp,
bool preserve_boundary,
bool adaptive_scale,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
/* Ensure that the triangulated mesh data is up to data */
const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(input_mesh);
@ -417,16 +417,19 @@ void BKE_mesh_remesh_sculpt_array_update(Object *ob, Mesh *target, Mesh *source)
const int target_totvert = target->totvert;
int *target_copy_index = (int *)MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
int *target_symmertry = (int *)MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
float (*target_orco)[3] = (float (*)[3])MEM_malloc_arrayN(target->totvert, sizeof(float) * 3, "array orco");
int *target_copy_index = (int *)MEM_malloc_arrayN(
sizeof(int), target_totvert, "target_copy_index");
int *target_symmertry = (int *)MEM_malloc_arrayN(
sizeof(int), target_totvert, "target_copy_index");
float(*target_orco)[3] = (float(*)[3])MEM_malloc_arrayN(
target->totvert, sizeof(float) * 3, "array orco");
for (int i = 0; i < target_totvert; i++) {
target_copy_index[i] = -1;
target_symmertry[i] = 0;
copy_v3_v3(target_orco[i], target->mvert[i].co);
}
for (int i = 0; i < target->totvert; i++) {
float from_co[3];
BVHTreeNearest nearest;
@ -449,23 +452,23 @@ void BKE_mesh_remesh_sculpt_array_update(Object *ob, Mesh *target, Mesh *source)
array->symmetry_pass = target_symmertry;
array->orco = target_orco;
for (int i = 0; i < target->totvert; i++) {
int array_index = target_copy_index[i];
int array_symm_pass = target_symmertry[i];
if (array_index == -1) {
continue;
}
SculptArrayCopy *copy = &array->copies[array_symm_pass][array_index];
float co[3];
float source_origin_symm[3];
copy_v3_v3(co, target->mvert[i].co);
/* TODO: MAke symmetry work here. */
//flip_v3_v3(source_origin_symm, array->source_origin, array_symm_pass);
mul_v3_m4v3(co, array->source_imat, co);
mul_v3_m4v3(co, copy->imat, co);
sub_v3_v3v3(co, co, source_origin_symm);
copy_v3_v3(array->orco[i], co);
}
for (int i = 0; i < target->totvert; i++) {
int array_index = target_copy_index[i];
int array_symm_pass = target_symmertry[i];
if (array_index == -1) {
continue;
}
SculptArrayCopy *copy = &array->copies[array_symm_pass][array_index];
float co[3];
float source_origin_symm[3];
copy_v3_v3(co, target->mvert[i].co);
/* TODO: MAke symmetry work here. */
// flip_v3_v3(source_origin_symm, array->source_origin, array_symm_pass);
mul_v3_m4v3(co, array->source_imat, co);
mul_v3_m4v3(co, copy->imat, co);
sub_v3_v3v3(co, co, source_origin_symm);
copy_v3_v3(array->orco[i], co);
}
}
void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)

View File

@ -778,7 +778,7 @@ static void version_geometry_nodes_change_legacy_names(bNodeTree *ntree)
}
/* NOLINTNEXTLINE: readability-function-size */
ATTR_NO_OPT void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
if (!MAIN_VERSION_ATLEAST(bmain, 300, 1)) {
/* Set default value for the new bisect_threshold parameter in the mirror modifier. */

View File

@ -11,7 +11,7 @@
using namespace std;
extern "C" {
ATTR_NO_OPT const char *sculpt_keymap_fix_intern(const char *str)
const char *sculpt_keymap_fix_intern(const char *str)
{
basic_string repl = regex_replace(str, regex("unified_"), "");
repl = regex_replace(repl, regex("size"), "radius");
@ -74,7 +74,7 @@ ATTR_NO_OPT const char *sculpt_keymap_fix_intern(const char *str)
return ret;
}
ATTR_NO_OPT static void test_regexp()
static void test_regexp()
{
// TODO: figure out blender's testing framework

View File

@ -373,7 +373,7 @@ static void fix_radial_control_path(IDProperty *prop, void *userdata)
free((void *)newstring);
}
ATTR_NO_OPT static bool keymap_radial_control_sculpt_fix(wmKeyMapItem *kmi)
static bool keymap_radial_control_sculpt_fix(wmKeyMapItem *kmi)
{
IDProperty *idprop = NULL;
char *string = NULL;

View File

@ -7193,7 +7193,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block,
return changed;
}
ATTR_NO_OPT static int ui_do_but_CURVE(
static int ui_do_but_CURVE(
bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
{
bool changed = false;

View File

@ -1013,7 +1013,7 @@ static void paint_cursor_update_unprojected_radius(UnifiedPaintSettings *ups,
bool use_brush_channels = paint_use_channels(vc->C);
/* Update the brush's cached 3D radius. */
if (!BKE_brush_use_locked_size(vc->scene, brush)) {
if (!BKE_brush_use_locked_size(vc->scene, brush, use_brush_channels)) {
/* Get 2D brush radius. */
if (ups->draw_anchored) {
projected_radius = ups->anchored_size;
@ -1036,7 +1036,7 @@ static void paint_cursor_update_unprojected_radius(UnifiedPaintSettings *ups,
}
/* Set cached value in either Brush or UnifiedPaintSettings. */
BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius);
BKE_brush_unprojected_radius_set(vc->scene, brush, unprojected_radius, use_brush_channels);
}
}
@ -1357,7 +1357,7 @@ static void paint_cursor_update_pixel_radius(PaintCursorContext *pcontext)
Brush *brush = BKE_paint_brush(pcontext->paint);
pcontext->pixel_radius = project_brush_radius(
&pcontext->vc,
BKE_brush_unprojected_radius_get(pcontext->scene, brush),
BKE_brush_unprojected_radius_get(pcontext->scene, brush, use_brush_channels),
pcontext->location);
if (pcontext->pixel_radius == 0) {
@ -1393,6 +1393,8 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext *pcon
pcontext->y - pcontext->region->winrct.ymin,
};
bool use_brush_channels = paint_use_channels(vc->C);
/* This updates the active vertex, which is needed for most of the Sculpt/Vertex Colors tools to
* work correctly */
pcontext->prev_active_vertex_index = ss->active_vertex_index;
@ -1409,8 +1411,8 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext *pcon
paint_cursor_update_pixel_radius(pcontext);
if (BKE_brush_use_locked_size(scene, brush)) {
BKE_brush_size_set(scene, brush, pcontext->pixel_radius, !!ss);
if (BKE_brush_use_locked_size(scene, brush, use_brush_channels)) {
BKE_brush_size_set(scene, brush, pcontext->pixel_radius, true);
}
if (pcontext->is_cursor_over_mesh) {
@ -1578,14 +1580,15 @@ static void paint_cursor_update_object_space_radius(PaintCursorContext *pcontext
{
bool use_brush_channels = paint_use_channels(pcontext->C);
if (!BKE_brush_use_locked_size(pcontext->scene, pcontext->brush)) {
if (!BKE_brush_use_locked_size(pcontext->scene, pcontext->brush, use_brush_channels)) {
pcontext->radius = paint_calc_object_space_radius(
&pcontext->vc,
pcontext->location,
BKE_brush_size_get(pcontext->scene, pcontext->brush, use_brush_channels));
}
else {
pcontext->radius = BKE_brush_unprojected_radius_get(pcontext->scene, pcontext->brush);
pcontext->radius = BKE_brush_unprojected_radius_get(
pcontext->scene, pcontext->brush, use_brush_channels);
}
}
@ -1677,7 +1680,10 @@ static void paint_cursor_preview_boundary_data_update(PaintCursorContext *pconte
}
ss->boundary_preview = SCULPT_boundary_data_init(pcontext->sd,
pcontext->vc.obact, pcontext->brush, ss->active_vertex_index, pcontext->radius);
pcontext->vc.obact,
pcontext->brush,
ss->active_vertex_index,
pcontext->radius);
}
static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *pcontext)

View File

@ -173,13 +173,14 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op)
/* unprojected radius */
{
float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(scene, brush);
float unprojected_radius = scalar * BKE_brush_unprojected_radius_get(
scene, brush, use_brush_channels);
if (unprojected_radius < 0.001f) { /* XXX magic number */
unprojected_radius = 0.001f;
}
BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius);
BKE_brush_unprojected_radius_set(scene, brush, unprojected_radius, true);
}
WM_main_add_notifier(NC_BRUSH | NA_EDITED, brush);

View File

@ -631,8 +631,10 @@ static float paint_space_stroke_spacing(bContext *C,
Paint *paint = BKE_paint_get_active_from_context(C);
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
float size_clamp = 0.0f;
float final_size_pressure = size_pressure;
if (brush->pressure_size_curve) {
BKE_curvemapping_init(brush->pressure_size_curve);
final_size_pressure = BKE_curvemapping_evaluateF(brush->pressure_size_curve, 0, size_pressure);
@ -640,14 +642,15 @@ static float paint_space_stroke_spacing(bContext *C,
float size = BKE_brush_size_get(scene, stroke->brush, mode == PAINT_MODE_SCULPT) *
final_size_pressure;
if (paint_stroke_use_scene_spacing(brush, mode)) {
if (!BKE_brush_use_locked_size(scene, brush)) {
if (!BKE_brush_use_locked_size(scene, brush, mode == PAINT_MODE_SCULPT)) {
float last_object_space_position[3];
mul_v3_m4v3(
last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position);
size_clamp = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
}
else {
size_clamp = BKE_brush_unprojected_radius_get(scene, brush) * final_size_pressure;
size_clamp = BKE_brush_unprojected_radius_get(scene, brush, mode == PAINT_MODE_SCULPT) *
final_size_pressure;
}
}
else {
@ -733,14 +736,15 @@ static float paint_space_get_final_size_intern(
float size = BKE_brush_size_get(scene, stroke->brush, mode == PAINT_MODE_SCULPT) * pressure;
if (paint_stroke_use_scene_spacing(stroke->brush, mode)) {
if (!BKE_brush_use_locked_size(scene, stroke->brush)) {
if (!BKE_brush_use_locked_size(scene, stroke->brush, mode == PAINT_MODE_SCULPT)) {
float last_object_space_position[3];
mul_v3_m4v3(
last_object_space_position, stroke->vc.obact->imat, stroke->last_world_space_position);
size = paint_calc_object_space_radius(&stroke->vc, last_object_space_position, size);
}
else {
size = BKE_brush_unprojected_radius_get(scene, stroke->brush) * pressure;
size = BKE_brush_unprojected_radius_get(scene, stroke->brush, mode == PAINT_MODE_SCULPT) *
pressure;
}
}

View File

@ -721,7 +721,7 @@ static int curvemapping_preset_get_path(
return 1;
}
ATTR_NO_OPT static int curvemapping_preset_exec(bContext *C, wmOperator *op)
static int curvemapping_preset_exec(bContext *C, wmOperator *op)
{
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));

View File

@ -1572,7 +1572,7 @@ static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, P
if (cache->first_time) {
cache->initial_radius = paint_calc_object_space_radius(
cache->vc, cache->true_location, BKE_brush_size_get(scene, brush, true));
BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius, true);
}
if (BKE_brush_use_size_pressure(brush) &&

View File

@ -140,10 +140,10 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
will be used (taking inheritence into account).
*/
ATTR_NO_OPT float SCULPT_get_float_intern(const SculptSession *ss,
const char *idname,
const Sculpt *sd,
const Brush *br)
float SCULPT_get_float_intern(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(
@ -165,10 +165,10 @@ ATTR_NO_OPT float SCULPT_get_float_intern(const SculptSession *ss,
}
}
ATTR_NO_OPT int SCULPT_get_int_intern(const SculptSession *ss,
const char *idname,
const Sculpt *sd,
const Brush *br)
int SCULPT_get_int_intern(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(
@ -3624,10 +3624,10 @@ static void calc_area_normal_and_center(
* values pull vertices, negative values push. Uses tablet pressure and a
* special multiplier found experimentally to scale the strength factor.
*/
ATTR_NO_OPT static float brush_strength(const Sculpt *sd,
const StrokeCache *cache,
const float feather,
const UnifiedPaintSettings *ups)
static float brush_strength(const Sculpt *sd,
const StrokeCache *cache,
const float feather,
const UnifiedPaintSettings *ups)
{
const Scene *scene = cache->vc->scene;
const Brush *brush = cache->brush; // BKE_paint_brush((Paint *)&sd->paint);
@ -3798,15 +3798,15 @@ ATTR_NO_OPT static float brush_strength(const Sculpt *sd,
}
/* Return a multiplier for brush strength on a particular vertex. */
ATTR_NO_OPT float SCULPT_brush_strength_factor(SculptSession *ss,
const Brush *br,
const float brush_point[3],
const float len,
const short vno[3],
const float fno[3],
const float mask,
const SculptVertRef vertex_index,
const int thread_id)
float SCULPT_brush_strength_factor(SculptSession *ss,
const Brush *br,
const float brush_point[3],
const float len,
const short vno[3],
const float fno[3],
const float mask,
const SculptVertRef vertex_index,
const int thread_id)
{
StrokeCache *cache = ss->cache;
const Scene *scene = cache->vc->scene;
@ -4236,9 +4236,9 @@ typedef struct {
bool original;
} SculptFindNearestToRayData;
ATTR_NO_OPT static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;
@ -8317,19 +8317,6 @@ static void sculpt_topology_update(Sculpt *sd,
/* build brush radius scale */
float radius_scale = 1.0f;
if (brush->autosmooth_factor > 0.0f) {
radius_scale = MAX2(radius_scale, brush->autosmooth_radius_factor);
}
if (brush->topology_rake_factor > 0.0f) {
radius_scale = MAX2(radius_scale, brush->topology_rake_factor);
}
/* multiply with primary radius scale instead of max */
if (brush->cached_dyntopo.radius_scale > 0.0f) {
radius_scale *= brush->cached_dyntopo.radius_scale;
}
/* Build a list of all nodes that are potentially within the brush's area of influence. */
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
ss->cache->original;
@ -8343,23 +8330,26 @@ static void sculpt_topology_update(Sculpt *sd,
PBVHTopologyUpdateMode mode = 0;
float location[3];
if (brush->cached_dyntopo.mode != DYNTOPO_DETAIL_MANUAL) {
if (brush->cached_dyntopo.flag & DYNTOPO_SUBDIVIDE) {
int dyntopo_mode = SCULPT_get_int(ss, dyntopo_mode, sd, brush);
int dyntopo_detail_mode = SCULPT_get_int(ss, dyntopo_detail_mode, sd, brush);
if (dyntopo_detail_mode != DYNTOPO_DETAIL_MANUAL) {
if (dyntopo_mode & DYNTOPO_SUBDIVIDE) {
mode |= PBVH_Subdivide;
}
else if (brush->cached_dyntopo.flag & DYNTOPO_LOCAL_SUBDIVIDE) {
else if (dyntopo_mode & DYNTOPO_LOCAL_SUBDIVIDE) {
mode |= PBVH_LocalSubdivide | PBVH_Subdivide;
}
if (brush->cached_dyntopo.flag & DYNTOPO_COLLAPSE) {
if (dyntopo_mode & DYNTOPO_COLLAPSE) {
mode |= PBVH_Collapse;
}
else if (brush->cached_dyntopo.flag & DYNTOPO_LOCAL_COLLAPSE) {
else if (dyntopo_mode & DYNTOPO_LOCAL_COLLAPSE) {
mode |= PBVH_LocalCollapse | PBVH_Collapse;
}
}
if (brush->cached_dyntopo.flag & DYNTOPO_CLEANUP) {
if (dyntopo_mode & DYNTOPO_CLEANUP) {
mode |= PBVH_Cleanup;
}
@ -8893,7 +8883,7 @@ void BKE_brush_commandlist_start(BrushCommandList *list,
Brush *brush,
BrushChannelSet *chset_final);
ATTR_NO_OPT static void SCULPT_run_command_list(
static void SCULPT_run_command_list(
Sculpt *sd, Object *ob, Brush *brush, BrushCommandList *list, UnifiedPaintSettings *ups)
{
SculptSession *ss = ob->sculpt;
@ -10593,13 +10583,13 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
/* Truly temporary data that isn't stored in properties. */
if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
if (!BKE_brush_use_locked_size(scene, brush)) {
if (!BKE_brush_use_locked_size(scene, brush, true)) {
cache->initial_radius = paint_calc_object_space_radius(
cache->vc, cache->true_location, BKE_brush_size_get(scene, brush, true));
BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius);
BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius, true);
}
else {
cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush);
cache->initial_radius = BKE_brush_unprojected_radius_get(scene, brush, true);
}
}
@ -10944,12 +10934,12 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
ss->rv3d = vc.rv3d;
ss->v3d = vc.v3d;
if (!BKE_brush_use_locked_size(scene, brush)) {
if (!BKE_brush_use_locked_size(scene, brush, true)) {
radius = paint_calc_object_space_radius(
&vc, out->location, BKE_brush_size_get(scene, brush, true));
}
else {
radius = BKE_brush_unprojected_radius_get(scene, brush);
radius = BKE_brush_unprojected_radius_get(scene, brush, true);
}
ss->cursor_radius = radius;
@ -11439,24 +11429,32 @@ void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerR
BKE_pbvh_set_symmetry(ss->pbvh, SCULPT_mesh_symmetry_xyz_get(ob), boundsym);
}
if (brush->cached_dyntopo.mode == DYNTOPO_DETAIL_CONSTANT ||
brush->cached_dyntopo.mode == DYNTOPO_DETAIL_MANUAL) {
float object_space_constant_detail = 1.0f / (brush->cached_dyntopo.constant_detail *
mat4_to_scale(ob->obmat));
BKE_pbvh_bmesh_detail_size_set(
ss->pbvh, object_space_constant_detail, brush->cached_dyntopo.detail_range);
int detail_mode = SCULPT_get_int(ss, dyntopo_detail_mode, sd, brush);
int dyntopo_mode = SCULPT_get_int(ss, dyntopo_mode, sd, brush);
float detail_size = SCULPT_get_float(ss, dyntopo_detail_size, sd, brush);
float detail_percent = SCULPT_get_float(ss, dyntopo_detail_percent, sd, brush);
float detail_range = SCULPT_get_float(ss, dyntopo_detail_range, sd, brush);
float constant_detail = SCULPT_get_float(ss, dyntopo_constant_detail, sd, brush);
float dyntopo_pixel_radius = ss->cache->radius;
float dyntopo_radius = paint_calc_object_space_radius(
ss->cache->vc, ss->cache->true_location, dyntopo_pixel_radius);
if (detail_mode == DYNTOPO_DETAIL_CONSTANT || detail_mode == DYNTOPO_DETAIL_MANUAL) {
float object_space_constant_detail = 1.0f / (constant_detail * mat4_to_scale(ob->obmat));
BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail, detail_range);
}
else if (brush->cached_dyntopo.mode == DYNTOPO_DETAIL_BRUSH) {
BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
ss->cache->radius * brush->cached_dyntopo.detail_percent /
100.0f,
brush->cached_dyntopo.detail_range);
else if (detail_mode == DYNTOPO_DETAIL_BRUSH) {
BKE_pbvh_bmesh_detail_size_set(
ss->pbvh, ss->cache->radius * detail_percent / 100.0f, detail_range);
}
else {
BKE_pbvh_bmesh_detail_size_set(ss->pbvh,
(ss->cache->radius / ss->cache->dyntopo_pixel_radius) *
(brush->cached_dyntopo.detail_size * U.pixelsize) / 0.4f,
brush->cached_dyntopo.detail_range);
(dyntopo_radius / dyntopo_pixel_radius) *
(detail_size * U.pixelsize) / 0.4f,
detail_range);
}
if (0 && !ss->cache->commandlist && SCULPT_stroke_is_dynamic_topology(ss, brush)) {
@ -13749,7 +13747,7 @@ typedef struct BMLinkItem {
int depth;
} BMLinkItem;
ATTR_NO_OPT static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
static int sculpt_regularize_rake_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;

View File

@ -304,7 +304,15 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *region,
if (srd.hit && srd.edge_length > 0.0f) {
/* Convert edge length to world space detail resolution. */
sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
float constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat));
BrushChannel *ch = BRUSHSET_LOOKUP(brush->channels, dyntopo_constant_detail);
if (ch->flag & BRUSH_CHANNEL_INHERIT) {
BKE_brush_channelset_ensure_builtin(sd->channels, "dyntopo_constant_detail");
ch = BRUSHSET_LOOKUP(sd->channels, dyntopo_constant_detail);
}
ch->fvalue = constant_detail;
}
}

View File

@ -74,14 +74,14 @@
#include <math.h>
#include <stdlib.h>
ATTR_NO_OPT void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
float result[3],
SculptVertRef vertex,
float projection,
float slide_fset,
float bound_smooth,
SculptCustomLayer *bound_scl,
bool do_origco)
void SCULPT_neighbor_coords_average_interior(SculptSession *ss,
float result[3],
SculptVertRef vertex,
float projection,
float slide_fset,
float bound_smooth,
SculptCustomLayer *bound_scl,
bool do_origco)
{
float avg[3] = {0.0f, 0.0f, 0.0f};
@ -1061,9 +1061,9 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
#else
ATTR_NO_OPT static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
SculptThreadedTaskData *data = userdata;
SculptSession *ss = data->ob->sculpt;

View File

@ -354,7 +354,7 @@ void ED_sculpt_update_modal_transform(struct bContext *C, Object *ob)
case SCULPT_TRANSFORM_MODE_RADIUS_ELASTIC: {
Brush *brush = BKE_paint_brush(&sd->paint);
Scene *scene = CTX_data_scene(C);
const float transform_radius = BKE_brush_unprojected_radius_get(scene, brush);
const float transform_radius = BKE_brush_unprojected_radius_get(scene, brush, true);
sculpt_transform_radius_elastic(sd, ob, transform_radius);
break;
}

View File

@ -253,10 +253,10 @@ static SnapObjectData *snap_object_data_lookup(SnapObjectContext *sctx, Object *
return sod;
}
ATTR_NO_OPT static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
Object *ob_eval,
const Mesh *me_eval,
bool use_hide)
static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx,
Object *ob_eval,
const Mesh *me_eval,
bool use_hide)
{
SnapObjectData *sod;
void **sod_p;

View File

@ -1500,13 +1500,13 @@ bool RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *v
return 0;
}
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)
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);
@ -3457,7 +3457,7 @@ int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
return eprop->defaultvalue;
}
ATTR_NO_OPT void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
{
EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
IDProperty *idprop;

View File

@ -810,6 +810,20 @@ static void rna_Brush_set_size(PointerRNA *ptr, int value)
/* scale unprojected radius so it stays consistent with brush size */
BKE_brush_scale_unprojected_radius(&brush->unprojected_radius, value, brush->size);
if (brush->channels) {
BrushChannel *ch = BRUSHSET_LOOKUP(brush->channels, unprojected_radius);
BrushChannel *rch = BRUSHSET_LOOKUP(brush->channels, radius);
if (ch) {
BKE_brush_scale_unprojected_radius(&ch->fvalue, value, rch ? (int)rch->fvalue : brush->size);
}
if (rch) {
rch->fvalue = (float)value;
}
}
brush->size = value;
}

View File

@ -40,9 +40,11 @@
#include "IMB_imbuf.h"
#include "BKE_brush.h"
#include "BKE_brush_engine.h"
#include "BKE_colortools.h"
#include "DNA_sculpt_brush_types.h"
#include "WM_types.h"
static EnumPropertyItem null_enum[2] = {{0, "null", ICON_NONE, "null"}, {0, NULL, 0, NULL, NULL}};
@ -75,13 +77,85 @@ int rna_BrushChannelSet_channels_assignint(struct PointerRNA *ptr,
float rna_BrushChannel_get_value(PointerRNA *rna)
{
BrushChannel *ch = rna->data;
BrushChannel *ch = (BrushChannel *)rna->data;
return ch->fvalue;
}
static BrushChannel *get_paired_radius_channel(PointerRNA *rna)
{
BrushChannel *ch = rna->data;
bool is_radius = STREQ(ch->idname, "radius");
bool is_unproj = STREQ(ch->idname, "unprojected_radius");
/*
the way the old brush system split view and scene
radii but presented them as the same to the user,
and also to parts of the API is proving difficult
to disentangle. . . - joeedh
*/
if ((is_radius || is_unproj) && rna->owner_id) {
BrushChannelSet *chset = NULL;
if (GS(rna->owner_id->name) == ID_SCE) {
Scene *scene = ((Scene *)rna->owner_id);
if (scene->toolsettings && scene->toolsettings->sculpt) {
chset = scene->toolsettings->sculpt->channels;
}
}
else if (GS(rna->owner_id->name) == ID_BR) {
chset = ((Brush *)rna->owner_id)->channels;
}
if (!chset) {
return NULL;
}
return is_radius ? BRUSHSET_LOOKUP(chset, unprojected_radius) : BRUSHSET_LOOKUP(chset, radius);
}
return NULL;
}
void rna_BrushChannel_inherit_set(PointerRNA *rna, bool value)
{
BrushChannel *ch = (BrushChannel *)rna->data;
BrushChannel *ch2 = get_paired_radius_channel(rna);
if (value) {
ch->flag |= BRUSH_CHANNEL_INHERIT;
if (ch2) {
ch2->flag |= BRUSH_CHANNEL_INHERIT;
}
}
else {
ch->flag &= ~BRUSH_CHANNEL_INHERIT;
if (ch2) {
ch2->flag &= ~BRUSH_CHANNEL_INHERIT;
}
}
}
bool rna_BrushChannel_inherit_get(PointerRNA *rna)
{
BrushChannel *ch = (BrushChannel *)rna->data;
return ch->flag & BRUSH_CHANNEL_INHERIT;
}
void rna_BrushChannel_set_value(PointerRNA *rna, float value)
{
BrushChannel *ch = rna->data;
BrushChannel *ch2 = get_paired_radius_channel(rna);
if (ch2 && value != 0.0f && ch->fvalue != 0.0f) {
float ratio = value / ch->fvalue;
ch2->fvalue *= ratio;
}
ch->fvalue = value;
}
@ -235,10 +309,10 @@ int lookup_icon_id(const char *icon)
return ICON_NONE;
}
ATTR_NO_OPT const EnumPropertyItem *rna_BrushChannel_enum_value_get_items(struct bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free)
const EnumPropertyItem *rna_BrushChannel_enum_value_get_items(struct bContext *C,
PointerRNA *ptr,
PropertyRNA *prop,
bool *r_free)
{
BrushChannel *ch = (BrushChannel *)ptr->data;
@ -471,7 +545,9 @@ void RNA_def_brush_channel(BlenderRNA *brna)
"rna_BrushChannel_value_range");
prop = RNA_def_property(srna, "inherit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_INHERIT);
// RNA_def_property_boolean_sdna(prop, "BrushChannel", "flag", BRUSH_CHANNEL_INHERIT);
RNA_def_property_boolean_funcs(
prop, "rna_BrushChannel_inherit_get", "rna_BrushChannel_inherit_set");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Inherit", "Inherit from scene defaults");

View File

@ -353,7 +353,7 @@ void pyrna_write_set(bool val)
{
rna_disallow_writes = !val;
}
#else /* USE_PEDANTIC_WRITE */
#else /* USE_PEDANTIC_WRITE */
bool pyrna_write_check(void)
{
return true;
@ -775,7 +775,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop)
ret = pyrna_prop_CreatePyObject(ptr, prop); /* Owned by the mathutils PyObject. */
}
}
#else /* USE_MATHUTILS */
#else /* USE_MATHUTILS */
(void)ptr;
(void)prop;
#endif /* USE_MATHUTILS */
@ -1297,7 +1297,7 @@ static int pyrna_prop_to_enum_bitfield(
return ret;
}
ATTR_NO_OPT static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val)
{
PyObject *item, *ret = NULL;
@ -1372,7 +1372,7 @@ ATTR_NO_OPT static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop
return ret;
}
ATTR_NO_OPT PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
{
PyObject *ret;
const int type = RNA_property_type(prop);
@ -1410,7 +1410,7 @@ ATTR_NO_OPT PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
else {
ret = PyUnicode_FromStringAndSize(buf, buf_len);
}
#else /* USE_STRING_COERCE */
#else /* USE_STRING_COERCE */
if (subtype == PROP_BYTESTRING) {
ret = PyBytes_FromStringAndSize(buf, buf_len);
}
@ -1537,7 +1537,7 @@ static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func)
return (PyObject *)pyfunc;
}
ATTR_NO_OPT static int pyrna_py_to_prop(
static int pyrna_py_to_prop(
PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix)
{
/* XXX hard limits should be checked here. */
@ -1723,7 +1723,7 @@ ATTR_NO_OPT static int pyrna_py_to_prop(
else {
param = PyUnicode_AsUTF8(value);
}
#else /* USE_STRING_COERCE */
#else /* USE_STRING_COERCE */
param = PyUnicode_AsUTF8(value);
#endif /* USE_STRING_COERCE */
@ -6507,7 +6507,7 @@ PyTypeObject pyrna_struct_Type = {
/* delete references to contained objects */
(inquiry)pyrna_struct_clear, /* inquiry tp_clear; */
#else
NULL, /* traverseproc tp_traverse; */
NULL, /* traverseproc tp_traverse; */
/* delete references to contained objects */
NULL, /* inquiry tp_clear; */