Sculpt-dev: sculpt_init_tool_override_channels

related fixes

Various fixes so sculpt_init_tool_override_channels
for shift-smooth can replicate the prior behavior:

* Brush spacing will now look up brush channel
  spacing directly for sculpt, instead of relying
  on copying the channel data into Brush.
* Brush spacing code will now use brush channel
  pressure for sculpt.  Fixes broken shift-smooth
  pen pressure.
* The falloff_curve channel is now automatically
  added (before it was only used internally by
  command lists, the code was defaulting to
  the Brush field otherwise).
* BrushCurve now has an option for custom curve
  presets to have negative slopes.
* The Falloff panel now puts the type dropbox
  inside the panel header.
* Falloff panel also now uses brush channel data in
  sculpt mode.
* falloff_shape is now a brush channel

In a somewhat unrelated change, I also unnested the
Brush Settings subpanels.  It's been driving me
insane for a very, very long time.  Much more
usable this way.
This commit is contained in:
Joseph Eagar 2021-11-25 11:34:24 -08:00
parent 9f45edd430
commit f13bedd649
24 changed files with 497 additions and 182 deletions

View File

@ -361,6 +361,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR "${NVCC_OUT}")
set(CUDA_VERSION "${CUDA_VERSION_MAJOR}${CUDA_VERSION_MINOR}")
# warn for other versions
if((CUDA_VERSION MATCHES "101") OR
(CUDA_VERSION MATCHES "102") OR
@ -406,6 +407,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
-D CCL_NAMESPACE_BEGIN=
-D CCL_NAMESPACE_END=
-D NVCC
-allow-unsupported-compiler
-m ${CUDA_BITS}
-I ${CMAKE_CURRENT_SOURCE_DIR}/..
-I ${CMAKE_CURRENT_SOURCE_DIR}/device/cuda

View File

@ -273,8 +273,8 @@ channel_name_map = {
expand_channels = {"direction", "radius_unit", "automasking"}
def template_curve(layout, base, propname, full_path):
layout.template_curve_mapping(base, propname, brush=True)
def template_curve(layout, base, propname, full_path, use_negative_slope=None):
layout.template_curve_mapping(base, propname, brush=True, use_negative_slope=use_negative_slope)
path = full_path
@ -286,6 +286,7 @@ def template_curve(layout, base, propname, full_path):
for i, shape in enumerate(shapes):
props = row.operator("brush.curve_preset_load", icon=icons[i], text="")
props.invert = use_negative_slope
props.shape = shape
props.path = path
@ -414,13 +415,16 @@ class UnifiedPaintPanel:
@staticmethod
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=None, text=None, baselayout=None,
slider=False, header=False, show_reorder=False, expand=None, toolsettings_only=False, ui_editing=None,
show_mappings=None):
show_mappings=None, brush_only=False, use_negative_slope=None):
""" Generalized way of adding brush options to the UI,
along with their pen pressure setting and global toggle
note that ui_editing is no longer a bool, it can also be "mappings_only"
to just show the input mappings controls.
"""
for curve channels, if use_negative_slope is None then
`channel.curve_preset_negative_slope` will be used.
"""
if baselayout is None:
baselayout = layout
@ -488,7 +492,7 @@ class UnifiedPaintPanel:
pressurech = ch
if ch.inherit or toolsettings_only:
if not brush_only and (ch.inherit or toolsettings_only):
sd = context.tool_settings.sculpt
# ensure channel exists in tool settings channel set
sd.channels.ensure(ch)
@ -527,9 +531,13 @@ class UnifiedPaintPanel:
if ch.type == "CURVE":
row.prop(finalch.curve, "curve_preset", text=text)
if finalch.curve.curve_preset == "CUSTOM":
if use_negative_slope is None:
use_negative_slope = finalch.curve.preset_slope_negative
if not header and finalch.curve.curve_preset == "CUSTOM":
path2 = path + ".curve.curve"
template_curve(layout, finalch.curve, "curve", path2)
template_curve(layout, finalch.curve, "curve", path2, use_negative_slope=use_negative_slope)
elif ch.type == "BITMASK":
if header or not expand:
@ -985,7 +993,11 @@ class StrokePanel(BrushPanel):
row.prop(brush, "spacing", text="Spacing")
if mode == 'SCULPT':
col.row().prop(brush, "use_scene_spacing", text="Spacing Distance", expand=True)
UnifiedPaintPanel.channel_unified(col,
context,
brush,
"use_scene_spacing", text="Spacing Distance", expand=True)
#col.row().prop(brush, "use_scene_spacing", text="Spacing Distance", expand=True)
if mode in {'PAINT_TEXTURE', 'PAINT_2D'}:
if brush.image_paint_capabilities.has_space_attenuation or brush.sculpt_capabilities.has_space_attenuation:
@ -1099,7 +1111,7 @@ class SmoothStrokePanel(BrushPanel):
class FalloffPanel(BrushPanel):
bl_label = "Falloff"
bl_label = ""
bl_options = {'DEFAULT_CLOSED'}
@classmethod
@ -1109,6 +1121,23 @@ class FalloffPanel(BrushPanel):
settings = cls.paint_settings(context)
return (settings and settings.brush and settings.brush.curve)
def draw_header(self, context):
layout = self.layout
settings = self.paint_settings(context)
mode = self.get_brush_mode(context)
brush = settings.brush
if 0 and mode == "SCULPT" and "falloff_curve" in brush.channels:
layout.label(text="Falloff")
ch = UnifiedPaintPanel.get_channel(context, brush, "falloff_curve")
layout.prop(ch.curve, "curve_preset", text="")
#UnifiedPaintPanel.channel_unified(layout, context, brush, "falloff_curve", use_negative_slope=True, header=True, text="")
return
else:
layout.label(text="Falloff")
layout.prop(brush, "curve_preset", text="")
def draw(self, context):
layout = self.layout
settings = self.paint_settings(context)
@ -1118,9 +1147,17 @@ class FalloffPanel(BrushPanel):
if brush is None:
return
if mode == "SCULPT" and "falloff_curve" in brush.channels:
ch, path = UnifiedPaintPanel.get_channel(context, brush, "falloff_curve", need_path=True)
path += ".curve.curve"
template_curve(layout, ch.curve, "curve", path, True)
#UnifiedPaintPanel.channel_unified(layout, context, brush, "falloff_shape", expand=True)
layout.prop(brush, "falloff_shape", expand=True)
return
col = layout.column(align=True)
row = col.row(align=True)
row.prop(brush, "curve_preset", text="")
if brush.curve_preset == 'CUSTOM':
layout.template_curve_mapping(brush, "curve", brush=True, use_negative_slope=False)

View File

@ -5357,11 +5357,17 @@ class VIEW3D_MT_sculpt_automasking_pie(Menu):
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
pie.prop(sculpt, "use_automasking_topology", text="Topology")
pie.prop(sculpt, "use_automasking_face_sets", text="Face Sets")
pie.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary")
pie.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary")
ch = UnifiedPaintPanel.get_channel(context, sculpt.brush, "automasking")
keys = ["TOPOLOGY", "FACE_SETS", "BOUNDARY_EDGE", "BOUNDARY_FACE_SETS"]
for item in ch.enum_items:
if item.identifier not in keys:
keys.append(item.identifier)
for key in keys:
print(key)
pie.prop_enum(ch, "value", key)
class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):

View File

@ -425,7 +425,7 @@ class VIEW3D_PT_tools_brush_settings_channels(Panel, View3DPaintBrushPanel):
class VIEW3D_PT_tools_brush_settings_channels_preview(Panel, View3DPaintBrushPanel):
bl_context = ".paint_common"
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Workspace Settings Preview"
@classmethod
@ -454,7 +454,7 @@ class VIEW3D_PT_tools_brush_settings_channels_preview(Panel, View3DPaintBrushPan
class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel):
bl_context = ".paint_common"
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Advanced"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 14
@ -473,7 +473,7 @@ class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel):
class VIEW3D_PT_tools_brush_color(Panel, View3DPaintPanel):
bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Color Picker"
@classmethod
@ -500,7 +500,7 @@ class VIEW3D_PT_tools_brush_color(Panel, View3DPaintPanel):
class VIEW3D_PT_tools_persistent_base_channels(Panel, View3DPaintPanel):
bl_context = ".paint_common"
bl_parent_id = "VIEW3D_PT_tools_brush_settings_channels"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings_channels"
bl_label = "Persistent Base"
bl_options = {'DEFAULT_CLOSED'}
@ -710,7 +710,7 @@ class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_display(Panel, View3DPaintBrushPanel, DisplayPanel):
bl_context = ".paint_common"
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Cursor"
bl_options = {'DEFAULT_CLOSED'}
bl_ui_units_x = 12
@ -719,7 +719,7 @@ class VIEW3D_PT_tools_brush_display(Panel, View3DPaintBrushPanel, DisplayPanel):
# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
bl_context = ".paint_common"
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
@ -753,7 +753,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel, TextureMaskPanel):
bl_category = "Tool"
bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Texture Mask"
bl_options = {'DEFAULT_CLOSED'}
@ -779,7 +779,7 @@ class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel, TextureMaskPanel):
class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel, StrokePanel):
bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_label = "Stroke"
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_options = {'DEFAULT_CLOSED'}
@ -826,15 +826,15 @@ class VIEW3D_PT_tools_weight_gradient(Panel, View3DPaintPanel):
# TODO, move to space_view3d.py
class VIEW3D_PT_tools_brush_falloff(Panel, View3DPaintPanel, FalloffPanel):
bl_context = ".paint_common" # dot on purpose (access from topbar)
bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = "Falloff"
#bl_parent_id = "VIEW3D_PT_tools_brush_settings"
bl_label = ""
bl_options = {'DEFAULT_CLOSED'}
class VIEW3D_PT_tools_brush_falloff_frontface(View3DPaintPanel, Panel):
bl_context = ".imagepaint" # dot on purpose (access from topbar)
bl_label = "Front-Face Falloff"
bl_parent_id = "VIEW3D_PT_tools_brush_falloff"
#bl_parent_id = "VIEW3D_PT_tools_brush_falloff"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
@ -1279,12 +1279,12 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
context,
brush,
"automasking_boundary_edges_propagation_steps",
toolsettings_only=True, ui_editing=False)
ui_editing=False)
UnifiedPaintPanel.channel_unified(layout.column(),
context,
brush,
"concave_mask_factor",
toolsettings_only=True, ui_editing=False, slider=True, show_mappings=True)
ui_editing=False, slider=True, show_mappings=True)
"""
col = layout.column(heading="Auto-Masking", align=True)

View File

@ -138,9 +138,12 @@ void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float
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);
bool BKE_brush_use_alpha_pressure(const struct ToolSettings *ts,
const struct Brush *brush,
bool use_channels);
bool BKE_brush_use_size_pressure(const struct ToolSettings *ts,
const struct Brush *brush,
bool use_channels);
bool BKE_brush_sculpt_has_secondary_color(const struct Brush *brush);
/* scale unprojected radius to reflect a change in the brush's 2D size */

View File

@ -78,6 +78,8 @@ struct UnifiedPaintSettings;
BKE_brush_channelset_get_int(chset, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_FINAL_INT(child, parent, channel, mapdata) \
BKE_brush_channelset_get_final_int(child, parent, MAKE_BUILTIN_CH_NAME(channel), mapdata)
#define BRUSHSET_GET_FINAL_BOOL(child, parent, channel, mapdata) \
BRUSHSET_GET_FINAL_INT(child, parent, channel, mapdata)
#define BRUSHSET_ENSURE_BUILTIN(chset, channel) \
BKE_brush_channelset_ensure_builtin(chset, MAKE_BUILTIN_CH_NAME(channel))
#define BRUSHSET_SET_FLOAT(chset, channel, val) \
@ -147,6 +149,7 @@ typedef struct BrushChannelType {
float fvalue;
float vector[4];
int curve_preset;
bool curve_preset_slope_neg;
BrushEnumDef enumdef[MAX_BRUSH_ENUM_DEF]; // for enum/bitmask types
EnumPropertyItem *rna_enumdef;
@ -203,6 +206,7 @@ void BKE_brush_channel_copy_data(BrushChannel *dst,
bool keep_mappings,
bool keep_idname_and_def);
void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def);
BrushChannelType *BKE_brush_builtin_channel_def_find(const char *name);
BrushChannelSet *BKE_brush_channelset_create(const char *info);
#ifdef DEBUG_CURVE_MAPPING_ALLOC
@ -248,13 +252,17 @@ void BKE_brush_channelset_inherit_mappings(BrushChannelSet *chset);
void BKE_brush_channelset_merge(BrushChannelSet *dst,
BrushChannelSet *child,
BrushChannelSet *parent);
void BKE_brush_channel_apply_mapping_flags(BrushChannel *dst,
BrushChannel *child,
BrushChannel *parent);
bool BKE_brush_mapping_is_enabled(BrushChannel *child, BrushChannel *parent, int mapping);
/*takes child and parent channels and builds inherited channel
in dst, with channel and brush mapping inheritance flags
properly resolved.
in dst, with channel and brush mapping inheritance flags
properly resolved.
note that child or parent may be NULL, but not both.
*/
note that child or parent may be NULL, but not both.
*/
void BKE_brush_channel_copy_final_data(BrushChannel *dst,
BrushChannel *src_child,
BrushChannel *src_parent,

View File

@ -218,8 +218,9 @@ void paint_update_brush_rake_rotation(struct UnifiedPaintSettings *ups,
float rotation);
void BKE_paint_stroke_get_average(struct Scene *scene, struct Object *ob, float stroke[3]);
bool BKE_paint_uses_channels(ePaintMode mode);
/* Tool slot API. */
/* Tool slot API. */
void BKE_paint_toolslots_init_from_main(struct Main *bmain);
void BKE_paint_toolslots_len_ensure(struct Paint *paint, int len);
void BKE_paint_toolslots_brush_update_ex(struct Paint *paint, struct Brush *brush);

View File

@ -330,6 +330,16 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
{
Brush *brush = (Brush *)id;
/* Falloff curve. */
BLO_read_data_address(reader, &brush->curve);
if (brush->curve) {
BKE_curvemapping_blend_read(reader, brush->curve);
}
else {
BKE_brush_curve_preset(brush, CURVE_PRESET_SHARP);
}
if (brush->channels) {
BLO_read_data_address(reader, &brush->channels);
@ -364,22 +374,12 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
brush->topology_rake_projection = 1.0f;
}
/* Falloff curve. */
BLO_read_data_address(reader, &brush->curve);
/* Input Curves. */
BLO_read_data_address(reader, &brush->pressure_size_curve);
BLO_read_data_address(reader, &brush->pressure_strength_curve);
BLO_read_data_address(reader, &brush->gradient);
if (brush->curve) {
BKE_curvemapping_blend_read(reader, brush->curve);
}
else {
BKE_brush_curve_preset(brush, CURVE_PRESET_SHARP);
}
if (brush->pressure_size_curve) {
BKE_curvemapping_blend_read(reader, brush->pressure_size_curve);
}
@ -2595,13 +2595,35 @@ bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush, bool use_
}
}
bool BKE_brush_use_size_pressure(const Brush *brush)
bool BKE_brush_use_size_pressure(const ToolSettings *ts, const Brush *brush, bool use_channels)
{
if (use_channels && brush->channels) {
BrushChannel *child_ch = BRUSHSET_LOOKUP(brush->channels, radius);
BrushChannel *parent_ch = ts && ts->sculpt && ts->sculpt->channels ?
BRUSHSET_LOOKUP(ts->sculpt->channels, radius) :
NULL;
if (child_ch || parent_ch) {
return BKE_brush_mapping_is_enabled(child_ch, parent_ch, BRUSH_MAPPING_PRESSURE);
}
}
return brush->flag & BRUSH_SIZE_PRESSURE;
}
bool BKE_brush_use_alpha_pressure(const Brush *brush)
bool BKE_brush_use_alpha_pressure(const ToolSettings *ts, const Brush *brush, bool use_channels)
{
if (use_channels && brush->channels) {
BrushChannel *child_ch = BRUSHSET_LOOKUP(brush->channels, strength);
BrushChannel *parent_ch = ts && ts->sculpt && ts->sculpt->channels ?
BRUSHSET_LOOKUP(ts->sculpt->channels, strength) :
NULL;
if (child_ch || parent_ch) {
return BKE_brush_mapping_is_enabled(child_ch, parent_ch, BRUSH_MAPPING_PRESSURE);
}
}
return brush->flag & BRUSH_ALPHA_PRESSURE;
}
@ -3055,7 +3077,5 @@ void BKE_brush_hard_edge_mode_set(Scene *scene, Brush *brush, bool val)
float BKE_brush_fset_slide_get(const Scene *scene, const Brush *brush)
{
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
return BKE_brush_hard_edge_mode_get(scene, brush) ? 0.0f : brush->autosmooth_fset_slide;
}

View File

@ -66,6 +66,9 @@ places in rna_engine_codebase are relevent:
# ifdef MAKE_CURVE
# undef MAKE_CURVE
# endif
# ifdef MAKE_CURVE_EX
# undef MAKE_CURVE_EX
# endif
# ifdef MAKE_BUILTIN_CH_DEF
# undef MAKE_BUILTIN_CH_DEF
@ -109,6 +112,8 @@ places in rna_engine_codebase are relevent:
# define MAKE_FLAGS_EX(idname1, name1, tooltip1, value1, flag1, enumdef1, ...) \
MAKE_BUILTIN_CH_DEF(idname1);
# define MAKE_CURVE(idname1, name1, tooltip1, preset1) MAKE_BUILTIN_CH_DEF(idname1);
# define MAKE_CURVE_EX(idname1, name1, tooltip1, preset1, flag, preset_slope_neg) \
MAKE_BUILTIN_CH_DEF(idname1);
#else
#endif
@ -195,6 +200,8 @@ MAKE_ENUM(blend,"Blending Mode","Brush blending mode",IMB_BLEND_MIX,{\
})
MAKE_FLOAT_EX(spacing,"Spacing","",10.0f,0.25f,1000.0f,1.0f,200.0f,false)
MAKE_BOOL(use_scene_spacing, "Scene Spacing", "Space brush in 3d space", false)
MAKE_FLOAT_EX(topology_rake,"Topology Rake","Automatically align edges to the brush direction to "
"generate cleaner topology and define sharp features. "
"Best used on low-poly meshes as it has a performance impact",0.0f,0.0f,5.0f,0.0f,2.0f,false)
@ -337,7 +344,7 @@ MAKE_ENUM(blend,"Blending Mode","Brush blending mode",IMB_BLEND_MIX,{\
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)
"from the fully masked edge",1,1,20,1,10)
MAKE_COLOR4(cursor_color_add,"Add Color","Color of cursor when adding",1.0f,0.39f,0.39f,1.0f)
MAKE_COLOR4(cursor_color_sub,"Subtract Color","Color of cursor when subtracting",0.39f,0.39f,1.0f,1.0f)
MAKE_COLOR3(color,"Color","",1.0f,1.0f,1.0f)
@ -465,9 +472,18 @@ MAKE_ENUM(blend,"Blending Mode","Brush blending mode",IMB_BLEND_MIX,{\
{-1}
})
MAKE_CURVE(autosmooth_falloff_curve,"Autosmooth Falloff","Custom curve for autosmooth",BRUSH_CURVE_SMOOTH)
MAKE_CURVE(topology_rake_falloff_curve,"Rake Falloff","Custom curve for topolgoy rake",BRUSH_CURVE_SMOOTH)
MAKE_CURVE(falloff_curve,"Falloff","Falloff curve",BRUSH_CURVE_SMOOTH)
MAKE_CURVE_EX(falloff_curve,"Falloff","Falloff curve",BRUSH_CURVE_SMOOTH, 0, true)
MAKE_ENUM(falloff_shape, "Falloff Shape", "Use projected or spherical falloff", 0, {\
{PAINT_FALLOFF_SHAPE_SPHERE, "SPHERE", "NONE", "Sphere", "Apply brush influence in a Sphere, outwards from the center"},
{PAINT_FALLOFF_SHAPE_TUBE,
"PROJECTED",
"NONE",
"Projected",
"Apply brush influence in a 2D circle, projected from the view"},
{-1},
})
MAKE_CURVE_EX(autosmooth_falloff_curve,"Autosmooth Falloff","Custom curve for autosmooth",BRUSH_CURVE_SMOOTH, 0, true)
MAKE_CURVE_EX(topology_rake_falloff_curve,"Rake Falloff","Custom curve for topolgoy rake",BRUSH_CURVE_SMOOTH, 0, true)
MAKE_FLOAT_EX(unprojected_radius,"Unprojected Radius","Radius of brush in Blender units",0.1f,0.001f,FLT_MAX,0.001f,1.0f,false)
MAKE_ENUM_EX(radius_unit,"Radius Unit","Measure brush size relative to the view or the scene",0,BRUSH_CHANNEL_SHOW_IN_WORKSPACE,{\
{0, "VIEW", "NONE", "View", "Measure brush size relative to the view"},
@ -669,4 +685,7 @@ MAKE_ENUM(blend,"Blending Mode","Brush blending mode",IMB_BLEND_MIX,{\
# ifdef MAKE_CURVE
# undef MAKE_CURVE
# endif
# ifdef MAKE_CURVE_EX
# undef MAKE_CURVE_EX
# endif
#endif

View File

@ -474,6 +474,7 @@ void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
ch->flag = def->flag;
ch->curve.preset = def->curve_preset;
ch->curve.preset_slope_negative = def->curve_preset_slope_neg;
ch->fvalue = def->fvalue;
ch->ivalue = def->ivalue;
copy_v4_v4(ch->vector, def->vector);
@ -550,12 +551,29 @@ CurveMapping *BKE_brush_channel_curvemapping_get(BrushCurve *curve, bool force_c
if ((force_create || curve->preset == BRUSH_CURVE_CUSTOM) && !curve->curve) {
CurveMapping *cumap = curve->curve = MEM_callocN(sizeof(CurveMapping), "channel CurveMapping");
BKE_curvemapping_set_defaults(cumap, 1, 0.0f, 0.0f, 1.0f, 1.0f);
int preset = CURVE_PRESET_LINE;
/* brush and curvemapping presets aren't perfectly compatible,
try to convert in reasonable manner*/
switch (curve->preset) {
case BRUSH_CURVE_SMOOTH:
case BRUSH_CURVE_SMOOTHER:
preset = CURVE_PRESET_SMOOTH;
break;
case BRUSH_CURVE_SHARP:
preset = CURVE_PRESET_SHARP;
break;
case BRUSH_CURVE_POW4:
preset = CURVE_PRESET_POW3;
break;
}
BKE_curvemapping_set_defaults(cumap, 1, 0.0f, 0.0f, 1.0f, 1.0f);
BKE_curvemap_reset(cumap->cm,
&(struct rctf){.xmin = 0, .ymin = 0.0, .xmax = 1.0, .ymax = 1.0},
CURVE_PRESET_LINE,
1);
preset,
curve->preset_slope_negative ? 0 : 1);
BKE_curvemapping_init(cumap);
}
@ -1143,10 +1161,31 @@ void BKE_brush_channel_set_int(BrushChannel *ch, int val)
ch->ivalue = val;
}
void brush_channel_apply_mapping_flags(BrushChannel *ch, BrushChannel *child, BrushChannel *parent)
bool BKE_brush_mapping_is_enabled(BrushChannel *child, BrushChannel *parent, int mapping)
{
if (child && parent) {
if (brush_mapping_inherits(child, child->mappings + mapping)) {
return child->mappings[mapping].flag & BRUSH_MAPPING_ENABLED;
}
else {
return parent->mappings[mapping].flag & BRUSH_MAPPING_ENABLED;
}
}
else if (child) {
return child->mappings[mapping].flag & BRUSH_MAPPING_ENABLED;
}
else if (parent) {
return parent->mappings[mapping].flag & BRUSH_MAPPING_ENABLED;
}
else {
return false;
}
}
void BKE_brush_channel_apply_mapping_flags(BrushChannel *dst, BrushChannel *child, BrushChannel *parent)
{
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
BrushMapping *mp = ch->mappings + i;
BrushMapping *mp = dst->mappings + i;
BrushMapping *cmp = child ? child->mappings + i : NULL;
BrushMapping *pmp = parent ? parent->mappings + i : NULL;
@ -1202,7 +1241,7 @@ int BKE_brush_channelset_get_final_int(BrushChannelSet *child,
if (ch) {
BrushChannel cpy = *ch;
brush_channel_apply_mapping_flags(&cpy, childch, parentch);
BKE_brush_channel_apply_mapping_flags(&cpy, childch, parentch);
return BKE_brush_channel_get_int(&cpy, mapdata);
}
@ -1250,7 +1289,7 @@ float BKE_brush_channelset_get_final_float(BrushChannelSet *child,
if (ch) {
BrushChannel cpy = *ch;
brush_channel_apply_mapping_flags(&cpy, childch, parentch);
BKE_brush_channel_apply_mapping_flags(&cpy, childch, parentch);
return BKE_brush_channel_get_float(&cpy, mapdata);
}
@ -1350,7 +1389,7 @@ int BKE_brush_channelset_get_final_vector(BrushChannelSet *child,
if (ch) {
BrushChannel cpy = *ch;
brush_channel_apply_mapping_flags(&cpy, childch, parentch);
BKE_brush_channel_apply_mapping_flags(&cpy, childch, parentch);
return BKE_brush_channel_get_vector(&cpy, r_vec, mapdata);
}

View File

@ -205,6 +205,17 @@ MAKE_FLOAT_EX_EX(idname1, name1, tooltip1, value1, min1, max1, smin1, smax1, pre
.curve_preset = preset1,\
},
# define MAKE_CURVE_EX(idname1, name1, tooltip1, preset1, flag1, preset_slope_neg) \
{\
.idname = #idname1,\
.name = name1,\
.tooltip = tooltip1,\
.type = BRUSH_CHANNEL_TYPE_CURVE,\
.curve_preset = preset1,\
.flag = flag1,\
.curve_preset_slope_neg = preset_slope_neg,\
},
/*
This is where all the builtin brush channels are defined.
That includes per-brush enums and bitflags!
@ -413,15 +424,11 @@ static bool check_builtin_init()
#ifdef ADDCH
# undef ADDCH
#endif
#ifdef GETCH
# 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 */
@ -519,6 +526,7 @@ static BrushSettingsMap brush_settings_map[] = {
DEF(array_count, array_count, INT, INT)
DEF(smear_deform_type, smear_deform_type, INT, INT)
DEF(slide_deform_type, slide_deform_type, INT, INT)
DEF(falloff_shape, falloff_shape, INT, INT)
};
static const int brush_settings_map_len = ARRAY_SIZE(brush_settings_map);
@ -593,6 +601,7 @@ BrushFlagMap brush_flags_map[] = {
DEF(flag, accumulate, BRUSH_ACCUMULATE)
DEF(flag, use_smooth_stroke, BRUSH_SMOOTH_STROKE)
DEFBIT(flag, jitter_unit, BRUSH_ABSOLUTE_JITTER, BRUSH_ABSOLUTE_JITTER)
DEF(flag, use_scene_spacing, BRUSH_SCENE_SPACING)
};
int brush_flags_map_len = ARRAY_SIZE(brush_flags_map);
@ -1039,11 +1048,47 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
ADDCH(radius);
ADDCH(spacing);
if (!BRUSHSET_LOOKUP(chset, use_scene_spacing)) {
BrushChannel *ch = ADDCH(use_scene_spacing);
BrushMapping *mp = ch->mappings + BRUSH_MAPPING_PRESSURE;
mp->max = 1.5;
mp->flag |= BRUSH_MAPPING_ENABLED | BRUSH_MAPPING_INVERT;
}
if (!BRUSHSET_LOOKUP(chset, falloff_shape)) {
ADDCH(falloff_shape);
BRUSHSET_SET_INT(chset, falloff_shape, brush->falloff_shape);
}
ADDCH(strength);
ADDCH(radius_unit);
ADDCH(unprojected_radius);
ADDCH(use_frontface);
/* if falloff curve hannel doesn't already exist, load it from
field in Brush */
if (!BRUSHSET_LOOKUP(chset, falloff_curve)) {
BrushChannel *ch = ADDCH(falloff_curve);
ch->curve.preset = brush->curve_preset;
if (brush->curve) {
ch->curve.curve = BKE_curvemapping_copy(brush->curve);
BKE_curvemapping_init(brush->curve);
}
else {
ch->curve.curve = MEM_callocN(sizeof(*ch->curve.curve), "ch->curve.curve");
BKE_curvemap_reset(ch->curve.curve->cm,
&(struct rctf){.xmin = 0, .ymin = 0.0, .xmax = 1.0, .ymax = 1.0},
CURVE_PRESET_SMOOTH,
1);
BKE_curvemapping_init(ch->curve.curve);
}
}
ADDCH(sharp_mode);
ADDCH(show_origco);
ADDCH(save_temp_layers);
@ -1638,17 +1683,21 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
BKE_brush_builtin_patch(brush, tool);
GETCH(dyntopo_detail_mode)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_mode)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_detail_range)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_detail_percent)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_detail_size)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_constant_detail)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_spacing)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(dyntopo_radius_scale)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, use_scene_spacing)->mappings[BRUSH_MAPPING_PRESSURE].max = 1.5;
BRUSHSET_LOOKUP(chset, use_scene_spacing)->mappings[BRUSH_MAPPING_PRESSURE].flag |=
BRUSH_MAPPING_ENABLED | BRUSH_MAPPING_INVERT;
// GETCH(strength)->flag |= BRUSH_CHANNEL_INHERIT;
GETCH(radius)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_detail_mode)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_mode)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_detail_range)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_detail_percent)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_detail_size)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_constant_detail)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_spacing)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, dyntopo_radius_scale)->flag |= BRUSH_CHANNEL_INHERIT;
// BRUSHSET_LOOKUP(chset, strength)->flag |= BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, radius)->flag |= BRUSH_CHANNEL_INHERIT;
ADDCH(area_radius_factor);
@ -1683,9 +1732,9 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
case SCULPT_TOOL_DISPLACEMENT_ERASER:
case SCULPT_TOOL_FAIRING:
case SCULPT_TOOL_SCENE_PROJECT:
GETCH(spacing)->fvalue = 10;
GETCH(strength)->fvalue = 1.0f;
GETCH(dyntopo_disabled)->ivalue = 1;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 10;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 1.0f;
BRUSHSET_LOOKUP(chset, dyntopo_disabled)->ivalue = 1;
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
break;
case SCULPT_TOOL_SMEAR:
@ -1704,10 +1753,10 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
break;
case SCULPT_TOOL_SLIDE_RELAX:
GETCH(spacing)->fvalue = 10;
GETCH(strength)->fvalue = 1.0f;
GETCH(dyntopo_disabled)->ivalue = 1;
GETCH(slide_deform_type)->ivalue = BRUSH_SLIDE_DEFORM_DRAG;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 10;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 1.0f;
BRUSHSET_LOOKUP(chset, dyntopo_disabled)->ivalue = 1;
BRUSHSET_LOOKUP(chset, slide_deform_type)->ivalue = BRUSH_SLIDE_DEFORM_DRAG;
break;
case SCULPT_TOOL_PAINT: {
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
@ -1721,16 +1770,18 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
break;
}
case SCULPT_TOOL_CLAY:
GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, radius)->mappings[BRUSH_MAPPING_PRESSURE].flag |=
BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag |=
BRUSH_MAPPING_ENABLED;
GETCH(spacing)->fvalue = 3;
GETCH(autosmooth)->fvalue = 0.25f;
GETCH(normal_radius_factor)->fvalue = 0.75f;
GETCH(hardness)->fvalue = 0.65;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 3;
BRUSHSET_LOOKUP(chset, autosmooth)->fvalue = 0.25f;
BRUSHSET_LOOKUP(chset, normal_radius_factor)->fvalue = 0.75f;
BRUSHSET_LOOKUP(chset, hardness)->fvalue = 0.65;
// ADDCH(autosmooth_falloff_curve);
// GETCH(autosmooth_falloff_curve)->curve.preset = BRUSH_CURVE_SPHERE;
// BRUSHSET_LOOKUP(chset, autosmooth_falloff_curve)->curve.preset = BRUSH_CURVE_SPHERE;
BRUSHSET_SET_BOOL(chset, autosmooth_use_spacing, true);
BRUSHSET_SET_FLOAT(chset, autosmooth_spacing, 7);
@ -1738,10 +1789,10 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
reset_clay_mappings(chset, false);
break;
case SCULPT_TOOL_TWIST:
GETCH(strength)->fvalue = 0.5f;
GETCH(normal_radius_factor)->fvalue = 1.0f;
GETCH(spacing)->fvalue = 6;
GETCH(hardness)->fvalue = 0.5;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 0.5f;
BRUSHSET_LOOKUP(chset, normal_radius_factor)->fvalue = 1.0f;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 6;
BRUSHSET_LOOKUP(chset, hardness)->fvalue = 0.5;
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
break;
case SCULPT_TOOL_CLAY_THUMB:
@ -1753,22 +1804,25 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
~BRUSH_MAPPING_ENABLED;
break;
case SCULPT_TOOL_CLAY_STRIPS: {
// GETCH(falloff_curve)->curve.preset = BRUSH_CURVE_SMOOTHER;
// BRUSHSET_LOOKUP(chset, falloff_curve)->curve.preset = BRUSH_CURVE_SMOOTHER;
GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag |= BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, radius)->mappings[BRUSH_MAPPING_PRESSURE].flag |=
BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag |=
BRUSH_MAPPING_ENABLED;
GETCH(strength)->flag &= ~BRUSH_CHANNEL_INHERIT;
BRUSHSET_LOOKUP(chset, strength)->flag &= ~BRUSH_CHANNEL_INHERIT;
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
GETCH(tip_roundness)->fvalue = 0.18f;
GETCH(normal_radius_factor)->fvalue = 1.35f;
GETCH(strength)->fvalue = 0.8f;
GETCH(accumulate)->ivalue = 1;
GETCH(spacing)->fvalue = 7.0f;
BRUSHSET_LOOKUP(chset, tip_roundness)->fvalue = 0.18f;
BRUSHSET_LOOKUP(chset, normal_radius_factor)->fvalue = 1.35f;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 0.8f;
BRUSHSET_LOOKUP(chset, accumulate)->ivalue = 1;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 7.0f;
BKE_brush_mapping_ensure_write(&GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE]);
BKE_brush_mapping_ensure_write(
&BRUSHSET_LOOKUP(chset, radius)->mappings[BRUSH_MAPPING_PRESSURE]);
reset_clay_mappings(chset, true);
@ -1796,57 +1850,62 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
ADDCH(use_multiplane_scrape_dynamic);
ADDCH(show_multiplane_scrape_planes_preview);
GETCH(strength)->fvalue = 0.7f;
GETCH(normal_radius_factor)->fvalue = 0.7f;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 0.7f;
BRUSHSET_LOOKUP(chset, normal_radius_factor)->fvalue = 0.7f;
ADDCH(multiplane_scrape_angle);
GETCH(spacing)->fvalue = 5.0f;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 5.0f;
break;
case SCULPT_TOOL_CREASE:
GETCH(direction)->ivalue = true;
GETCH(strength)->fvalue = 0.25f;
GETCH(crease_pinch_factor)->fvalue = 0.5f;
BRUSHSET_LOOKUP(chset, direction)->ivalue = true;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 0.25f;
BRUSHSET_LOOKUP(chset, crease_pinch_factor)->fvalue = 0.5f;
break;
case SCULPT_TOOL_SCRAPE:
case SCULPT_TOOL_FILL:
GETCH(strength)->fvalue = 0.7f;
GETCH(area_radius_factor)->fvalue = 0.5f;
GETCH(spacing)->fvalue = 7.0f;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 0.7f;
BRUSHSET_LOOKUP(chset, area_radius_factor)->fvalue = 0.5f;
BRUSHSET_LOOKUP(chset, spacing)->fvalue = 7.0f;
ADDCH(invert_to_scrape_fill);
GETCH(invert_to_scrape_fill)->ivalue = true;
GETCH(accumulate)->ivalue = true;
BRUSHSET_LOOKUP(chset, invert_to_scrape_fill)->ivalue = true;
BRUSHSET_LOOKUP(chset, accumulate)->ivalue = true;
break;
case SCULPT_TOOL_ROTATE:
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
GETCH(strength)->fvalue = 1.0;
GETCH(dyntopo_disabled)->ivalue = true;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 1.0;
BRUSHSET_LOOKUP(chset, dyntopo_disabled)->ivalue = true;
break;
case SCULPT_TOOL_CLOTH:
BRUSHSET_SET_BOOL(chset, cloth_pin_simulation_boundary, true);
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
GETCH(radius)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, radius)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
ADDCH(elastic_deform_type);
ADDCH(elastic_deform_volume_preservation);
break;
case SCULPT_TOOL_ELASTIC_DEFORM:
ADDCH(elastic_deform_type);
ADDCH(elastic_deform_volume_preservation);
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
break;
case SCULPT_TOOL_GRAB:
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
GETCH(strength)->fvalue = 0.4f;
GETCH(radius)->fvalue = 75.0f;
GETCH(dyntopo_disabled)->ivalue = 1;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 0.4f;
BRUSHSET_LOOKUP(chset, radius)->fvalue = 75.0f;
BRUSHSET_LOOKUP(chset, dyntopo_disabled)->ivalue = 1;
break;
case SCULPT_TOOL_SNAKE_HOOK:
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
GETCH(dyntopo_mode)->ivalue = DYNTOPO_LOCAL_COLLAPSE | DYNTOPO_SUBDIVIDE;
GETCH(dyntopo_mode)->flag = BRUSH_CHANNEL_INHERIT_IF_UNSET;
GETCH(strength)->fvalue = 1.0f;
BRUSHSET_LOOKUP(chset, dyntopo_mode)->ivalue = DYNTOPO_LOCAL_COLLAPSE | DYNTOPO_SUBDIVIDE;
BRUSHSET_LOOKUP(chset, dyntopo_mode)->flag = BRUSH_CHANNEL_INHERIT_IF_UNSET;
BRUSHSET_LOOKUP(chset, strength)->fvalue = 1.0f;
ADDCH(elastic_deform_type);
ADDCH(elastic_deform_volume_preservation);
@ -1860,13 +1919,15 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
break;
case SCULPT_TOOL_BOUNDARY:
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
ADDCH(elastic_deform_type);
ADDCH(elastic_deform_volume_preservation);
break;
case SCULPT_TOOL_POSE:
GETCH(strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &= ~BRUSH_MAPPING_ENABLED;
BRUSHSET_LOOKUP(chset, strength)->mappings[BRUSH_MAPPING_PRESSURE].flag &=
~BRUSH_MAPPING_ENABLED;
BRUSHSET_SET_BOOL(chset, use_space_attenuation, false);
ADDCH(elastic_deform_type);
ADDCH(elastic_deform_volume_preservation);

View File

@ -3348,3 +3348,8 @@ void BKE_sculptsession_update_attr_refs(Object *ob)
ss->totuv = ss->ldata ? CustomData_number_of_layers(ss->ldata, CD_MLOOPUV) : 0;
}
}
bool BKE_paint_uses_channels(ePaintMode mode)
{
return mode == PAINT_MODE_SCULPT;
}

View File

@ -4394,7 +4394,7 @@ void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
mv->flag &= ~SCULPTVERT_NEED_VALENCE;
}
void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
ATTR_NO_OPT void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
MVert *mvert,
MEdge *medge,
MLoop *mloop,

View File

@ -2633,6 +2633,39 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
/* fix custom presets of autosmooth/toplogy-rake falloff curves */
if (!MAIN_VERSION_ATLEAST(bmain, 301, 5)) {
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (!brush->channels) {
continue;
}
const char *names[] = {"autosmooth_falloff_curve", "topology_rake_falloff_curve"};
LISTBASE_FOREACH (BrushChannel *, ch, &brush->channels->channels) {
if (ch->type != BRUSH_CHANNEL_TYPE_CURVE) {
continue;
}
bool ok = false;
for (int i = 0; i < ARRAY_SIZE(names); i++) {
if (STREQ(names[i], ch->idname)) {
ok = true;
break;
}
}
if (ok) {
BrushChannelType *def = ch->def;
BKE_brush_channel_free_data(ch);
BKE_brush_channel_init(ch, def);
}
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -589,7 +589,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
GPU_matrix_translate_2f(-x, -y);
/* Scale based on tablet pressure. */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(CTX_data_scene(vc->C)->toolsettings, brush, use_brush_channels)) {
const float scale = ups->size_pressure_value;
GPU_matrix_translate_2f(x, y);
GPU_matrix_scale_2f(scale, scale);
@ -728,7 +728,7 @@ static bool paint_draw_cursor_overlay(
}
/* Scale based on tablet pressure. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
if (ups->stroke_active && BKE_brush_use_size_pressure(CTX_data_scene(vc->C)->toolsettings, brush, paint_use_channels(vc->C))) {
do_pop = true;
GPU_matrix_push();
GPU_matrix_translate_2fv(center);
@ -1031,7 +1031,9 @@ static void paint_cursor_update_unprojected_radius(UnifiedPaintSettings *ups,
unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius);
/* Scale 3D brush radius by pressure. */
if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) {
if (ups->stroke_active && BKE_brush_use_size_pressure(CTX_data_scene(vc->C)->toolsettings,
brush,
use_brush_channels)) {
unprojected_radius *= ups->size_pressure_value;
}
@ -1434,7 +1436,7 @@ static void paint_draw_2D_view_brush_cursor(PaintCursorContext *pcontext)
immUniformColor3fvAlpha(pcontext->outline_col, pcontext->outline_alpha);
/* Draw brush outline. */
if (pcontext->ups->stroke_active && BKE_brush_use_size_pressure(pcontext->brush)) {
if (pcontext->ups->stroke_active && BKE_brush_use_size_pressure(CTX_data_scene(pcontext->C)->toolsettings, pcontext->brush, paint_use_channels(pcontext->C))) {
imm_draw_circle_wire_2d(pcontext->pos,
pcontext->translation[0],
pcontext->translation[1],

View File

@ -554,7 +554,7 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po
return;
}
if (BKE_brush_use_alpha_pressure(brush)) {
if (BKE_brush_use_alpha_pressure(scene->toolsettings, brush, paint_use_channels(C))) {
BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac));
}
else {

View File

@ -458,7 +458,7 @@ enum eBlurKernelType;
BlurKernel *paint_new_blur_kernel(struct Brush *br, bool proj);
void paint_delete_blur_kernel(BlurKernel *);
#define paint_use_channels(C) (BKE_paintmode_get_active_from_context(C) == PAINT_MODE_SCULPT)
#define paint_use_channels(C) BKE_paint_uses_channels(BKE_paintmode_get_active_from_context(C))
/* paint curve defines */
#define PAINT_CURVE_NUM_SEGMENTS 40

View File

@ -178,11 +178,12 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
return true;
}
static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode)
static bool paint_stroke_use_scene_spacing(ToolSettings *ts, Brush *brush, ePaintMode mode)
{
switch (mode) {
case PAINT_MODE_SCULPT:
return brush->flag & BRUSH_SCENE_SPACING;
return BRUSHSET_GET_FINAL_BOOL(brush->channels, ts->sculpt->channels, use_scene_spacing, NULL);
//return brush->flag & BRUSH_SCENE_SPACING;
default:
break;
}
@ -304,7 +305,8 @@ static bool paint_brush_update(bContext *C,
ups->pixel_radius = BKE_brush_size_get(scene, brush, mode == PAINT_MODE_SCULPT);
ups->initial_pixel_radius = BKE_brush_size_get(scene, brush, mode == PAINT_MODE_SCULPT);
if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, mode)) {
if (BKE_brush_use_size_pressure(scene->toolsettings, brush, BKE_paint_uses_channels(mode)) &&
paint_supports_dynamic_size(brush, mode)) {
ups->pixel_radius *= stroke->cached_size_pressure;
}
@ -521,7 +523,7 @@ static void paint_brush_stroke_add_step(bContext *C,
copy_v2_v2(stroke->last_mouse_position, mouse_in);
stroke->last_pressure = pressure;
if (paint_stroke_use_scene_spacing(brush, mode)) {
if (paint_stroke_use_scene_spacing(scene->toolsettings, brush, mode)) {
SCULPT_stroke_get_location(C, stroke->last_world_space_position, stroke->last_mouse_position);
mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
}
@ -641,7 +643,7 @@ 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 (paint_stroke_use_scene_spacing(scene->toolsettings, brush, mode)) {
if (!BKE_brush_use_locked_size(scene, brush, mode == PAINT_MODE_SCULPT)) {
float last_object_space_position[3];
mul_v3_m4v3(
@ -659,11 +661,36 @@ static float paint_space_stroke_spacing(bContext *C,
size_clamp = max_ff(1.0f, size);
}
float spacing = stroke->brush->spacing;
float spacing;
/* apply spacing pressure */
if (stroke->brush->flag & BRUSH_SPACING_PRESSURE) {
spacing = spacing * (1.5f - spacing_pressure);
if (paint_use_channels(C)) {
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Sculpt *sd = scene->toolsettings->sculpt;
BrushMappingData mapping = {0};
if (ss->cache) {
mapping = ss->cache->input_mapping;
}
/* apply spacing pressure */
//mapping.pressure = 1.5f - spacing_pressure;
mapping.pressure = spacing_pressure;
if (ss->cache && ss->cache->channels_final) {
spacing = BRUSHSET_GET_FLOAT(ss->cache->channels_final, spacing, &mapping);
}
else {
spacing = BRUSHSET_GET_FINAL_FLOAT(stroke->brush->channels, sd->channels, spacing, &mapping);
}
}
else {
spacing = stroke->brush->spacing;
/* apply spacing pressure */
if (stroke->brush->flag & BRUSH_SPACING_PRESSURE) {
spacing = spacing * (1.5f - spacing_pressure);
}
}
if (SCULPT_is_cloth_deform_brush(brush)) {
@ -678,7 +705,7 @@ static float paint_space_stroke_spacing(bContext *C,
* the fact that brush can be scaled there. */
spacing *= stroke->zoom_2d;
if (paint_stroke_use_scene_spacing(brush, mode)) {
if (paint_stroke_use_scene_spacing(scene->toolsettings, brush, mode)) {
return max_ff(0.001f, size_clamp * spacing / 50.0f);
}
return max_ff(stroke->zoom_2d, size_clamp * spacing / 50.0f);
@ -735,7 +762,7 @@ static float paint_space_get_final_size_intern(
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
float size = BKE_brush_size_get(scene, stroke->brush, mode == PAINT_MODE_SCULPT) * pressure;
if (paint_stroke_use_scene_spacing(stroke->brush, mode)) {
if (paint_stroke_use_scene_spacing(scene->toolsettings, stroke->brush, mode)) {
if (!BKE_brush_use_locked_size(scene, stroke->brush, mode == PAINT_MODE_SCULPT)) {
float last_object_space_position[3];
mul_v3_m4v3(
@ -758,7 +785,9 @@ static float paint_space_get_final_size(bContext *C,
float dpressure,
float length)
{
if (BKE_brush_use_size_pressure(stroke->brush)) {
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
if (BKE_brush_use_size_pressure(
scene->toolsettings, stroke->brush, BKE_paint_uses_channels(mode))) {
/* use pressure to modify size. set spacing so that at 100%, the circles
* are aligned nicely with no overlap. for this the spacing needs to be
* the average of the previous and next size. */
@ -789,7 +818,10 @@ static float paint_space_stroke_spacing_variable(bContext *C,
float dpressure,
float length)
{
if (BKE_brush_use_size_pressure(stroke->brush)) {
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
if (BKE_brush_use_size_pressure(
scene->toolsettings, stroke->brush, BKE_paint_uses_channels(mode))) {
/* use pressure to modify size. set spacing so that at 100%, the circles
* are aligned nicely with no overlap. for this the spacing needs to be
* the average of the previous and next size. */
@ -831,7 +863,7 @@ static int paint_space_stroke(bContext *C,
Brush *brush = BKE_paint_brush(paint);
int cnt = 0;
const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
const bool use_scene_spacing = paint_stroke_use_scene_spacing(scene->toolsettings, brush, mode);
float d_world_space_position[3] = {0.0f};
float no_pressure_spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
@ -1220,7 +1252,7 @@ static void paint_line_strokes_spacing(bContext *C,
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
ARegion *region = CTX_wm_region(C);
const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
const bool use_scene_spacing = paint_stroke_use_scene_spacing(CTX_data_scene(C)->toolsettings, brush, mode);
float mouse[2], dmouse[2];
float length;
@ -1377,7 +1409,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
stroke->last_pressure = 1.0;
copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
if (paint_stroke_use_scene_spacing(br, BKE_paintmode_get_active_from_context(C))) {
if (paint_stroke_use_scene_spacing(scene->toolsettings, br, BKE_paintmode_get_active_from_context(C))) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, data + 2 * j);
mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
@ -1509,7 +1541,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
stroke->last_pressure = sample_average.pressure;
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
if (paint_stroke_use_scene_spacing(br, mode)) {
if (paint_stroke_use_scene_spacing(CTX_data_scene(C)->toolsettings, br, mode)) {
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
C, stroke->last_world_space_position, sample_average.mouse);
mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);

View File

@ -1575,7 +1575,7 @@ static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, P
BKE_brush_unprojected_radius_set(scene, brush, cache->initial_radius, false);
}
if (BKE_brush_use_size_pressure(brush) &&
if (BKE_brush_use_size_pressure(scene->toolsettings, brush, paint_use_channels(C)) &&
paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
cache->radius = cache->initial_radius * cache->pressure;
}
@ -1756,12 +1756,18 @@ static void get_brush_alpha_data(const Scene *scene,
const Brush *brush,
float *r_brush_size_pressure,
float *r_brush_alpha_value,
float *r_brush_alpha_pressure)
float *r_brush_alpha_pressure,
bool use_channels)
{
*r_brush_size_pressure = BKE_brush_size_get(scene, brush, false) *
(BKE_brush_use_size_pressure(brush) ? ss->cache->pressure : 1.0f);
(BKE_brush_use_size_pressure(scene->toolsettings, brush, use_channels) ?
ss->cache->pressure :
1.0f);
*r_brush_alpha_value = BKE_brush_alpha_get(scene, brush);
*r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(brush) ? ss->cache->pressure : 1.0f);
*r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(
scene->toolsettings, brush, use_channels) ?
ss->cache->pressure :
1.0f);
}
static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi)
@ -1833,8 +1839,13 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
Scene *scene = CTX_data_scene(data->C);
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(
scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
get_brush_alpha_data(scene,
ss,
brush,
&brush_size_pressure,
&brush_alpha_value,
&brush_alpha_pressure,
paint_use_channels(data->C));
const bool use_normal = vwpaint_use_normal(data->vp);
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
@ -1923,8 +1934,13 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
const Scene *scene = CTX_data_scene(data->C);
const StrokeCache *cache = ss->cache;
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(
scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
get_brush_alpha_data(scene,
ss,
brush,
&brush_size_pressure,
&brush_alpha_value,
&brush_alpha_pressure,
paint_use_channels(data->C));
const bool use_normal = vwpaint_use_normal(data->vp);
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
@ -2035,8 +2051,13 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
* however in this case we calculate a new weight each time. */
const float paintweight = data->strength;
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(
scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
get_brush_alpha_data(scene,
ss,
brush,
&brush_size_pressure,
&brush_alpha_value,
&brush_alpha_pressure,
paint_use_channels(data->C));
const bool use_normal = vwpaint_use_normal(data->vp);
const bool use_face_sel = (data->me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
@ -2873,8 +2894,13 @@ static void do_vpaint_brush_draw_task_cb_ex(void *__restrict userdata,
uint *lcol = data->lcol;
const Scene *scene = CTX_data_scene(data->C);
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(
scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
get_brush_alpha_data(scene,
ss,
brush,
&brush_size_pressure,
&brush_alpha_value,
&brush_alpha_pressure,
paint_use_channels(data->C));
const bool use_normal = vwpaint_use_normal(data->vp);
const bool use_vert_sel = (data->me->editflag &
(ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
@ -2971,8 +2997,13 @@ static void do_vpaint_brush_blur_task_cb_ex(void *__restrict userdata,
const StrokeCache *cache = ss->cache;
uint *lcol = data->lcol;
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(
scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
get_brush_alpha_data(scene,
ss,
brush,
&brush_size_pressure,
&brush_alpha_value,
&brush_alpha_pressure,
paint_use_channels(data->C));
const bool use_normal = vwpaint_use_normal(data->vp);
const bool use_vert_sel = (data->me->editflag &
(ME_EDIT_PAINT_FACE_SEL | ME_EDIT_PAINT_VERT_SEL)) != 0;
@ -3088,8 +3119,13 @@ static void do_vpaint_brush_smear_task_cb_ex(void *__restrict userdata,
const StrokeCache *cache = ss->cache;
uint *lcol = data->lcol;
float brush_size_pressure, brush_alpha_value, brush_alpha_pressure;
get_brush_alpha_data(
scene, ss, brush, &brush_size_pressure, &brush_alpha_value, &brush_alpha_pressure);
get_brush_alpha_data(scene,
ss,
brush,
&brush_size_pressure,
&brush_alpha_value,
&brush_alpha_pressure,
paint_use_channels(data->C));
float brush_dir[3];
const bool use_normal = vwpaint_use_normal(data->vp);
const bool use_vert_sel = (data->me->editflag &

View File

@ -1731,7 +1731,7 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(const SculptSessi
return true;
}
bool SCULPT_vertex_has_unique_face_set(const SculptSession *ss, SculptVertRef vertex)
ATTR_NO_OPT bool SCULPT_vertex_has_unique_face_set(const SculptSession *ss, SculptVertRef vertex)
{
return !SCULPT_vertex_is_boundary(ss, vertex, SCULPT_BOUNDARY_FACE_SET);
}
@ -2422,7 +2422,8 @@ static void grids_update_boundary_flags(const SculptSession *ss, SculptVertRef v
}
}
static void faces_update_boundary_flags(const SculptSession *ss, const SculptVertRef vertex)
ATTR_NO_OPT static void faces_update_boundary_flags(const SculptSession *ss,
const SculptVertRef vertex)
{
BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
ss->mvert,
@ -2522,9 +2523,9 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
return ret;
}
SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
const SculptVertRef vertex,
SculptBoundaryType boundary_types)
ATTR_NO_OPT SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
const SculptVertRef vertex,
SculptBoundaryType boundary_types)
{
MSculptVert *mv = NULL;
@ -7702,7 +7703,10 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
}
}
if (BKE_brush_use_size_pressure(brush) &&
if (BKE_brush_use_size_pressure(
scene->toolsettings,
brush,
BKE_paint_uses_channels(BKE_paintmode_get_active_from_context(C))) &&
paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) {
cache->radius = sculpt_brush_dynamic_size_get(brush, cache, cache->initial_radius);
cache->dyntopo_pixel_radius = sculpt_brush_dynamic_size_get(
@ -8185,7 +8189,7 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op)
BKE_sculpt_update_object_for_edit(depsgraph, ob, is_smooth, need_mask, needs_colors);
}
static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
static void sculpt_restore_mesh(Scene *scene, Sculpt *sd, Object *ob)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
@ -8199,7 +8203,7 @@ static void sculpt_restore_mesh(Sculpt *sd, Object *ob)
/* Restore the mesh before continuing with anchored stroke. */
if ((brush->flag & BRUSH_ANCHORED) ||
((ELEM(SCULPT_get_tool(ss, brush), SCULPT_TOOL_GRAB, SCULPT_TOOL_ELASTIC_DEFORM)) &&
BKE_brush_use_size_pressure(brush)) ||
BKE_brush_use_size_pressure(scene->toolsettings, brush, true)) ||
(brush->flag & BRUSH_DRAG_DOT)) {
for (int i = 0; i < ss->totfaces; i++) {
@ -8552,7 +8556,7 @@ void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerR
if (itemptr) {
sculpt_update_cache_variants(C, sd, ob, itemptr);
}
sculpt_restore_mesh(sd, ob);
sculpt_restore_mesh(CTX_data_scene(C), sd, ob);
int boundsym = BKE_get_fset_boundary_symflag(ob);
ss->cache->boundary_symmetry = boundsym;

View File

@ -324,7 +324,7 @@ static void sculpt_face_sets_automasking_init(Sculpt *sd,
#define EDGE_DISTANCE_INF -1
void SCULPT_boundary_automasking_init(Object *ob,
ATTR_NO_OPT void SCULPT_boundary_automasking_init(Object *ob,
eBoundaryAutomaskMode mode,
int propagation_steps,
SculptCustomLayer *factorlayer)

View File

@ -49,6 +49,7 @@ struct Object;
struct SculptUndoNode;
struct bContext;
struct BrushChannelSet;
struct TaskParallelTLS;
enum ePaintSymmetryFlags;

View File

@ -48,7 +48,9 @@ typedef struct BrushMapping {
typedef struct BrushCurve {
CurveMapping *curve;
int preset, _pad[1]; // see eBrushCurvePreset, this differs from the one in BrushMappingDef
int preset; // see eBrushCurvePreset, this differs from the one in BrushMappingDef
char preset_slope_negative;
char _pad[3];
} BrushCurve;
typedef struct BrushChannel {

View File

@ -851,6 +851,11 @@ void RNA_def_brush_curve(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_pointer_funcs(prop, "rna_BrushCurve_curve_get", NULL, NULL, NULL);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
prop = RNA_def_property(srna, "preset_slope_negative", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(prop, "Negative Slope", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
}
void RNA_def_brush_channel(BlenderRNA *brna)
@ -1056,7 +1061,6 @@ void RNA_def_brush_channel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Curve", "Curve");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
// PROP_ENUM_FLAG
}
void RNA_def_brush_channelset(BlenderRNA *brna, PropertyRNA *cprop, const char *type_prefix)