Sculpt: brush input mappings improvements
Cleaned up brush channel input mappings: * BrushMapping now stores .min/.max * BrushMappingDef .min/max now sets BrushMapping min/max instead of changing the curve preset bounds. * Fixed how BKE_brush_channel_eval_mappings evaluates the mappings stack. Mappings now blend directly with channel value instead of accumulating a multiplier that's applied at the end. * Consequently, BrushMapping->blendmode now defaults to MA_BLEND_MULT. * Exposed BrushMapping->blendmode in RNA and UI. Note that it doesn't support every MA_BLEND_ type, it provides its own EnumPropertyItem list of supported blendmodes. * Added a random input method, BRUSH_MAPPING_RANDOM. * Fixed BRUSH_MAPPING_ANGLE being given data in the wrong range (all channels should be 0..1, not -pi..pi). Other changes: * Improved the uv smooth brush. It's still hidden behind an experimental pref. * Added a SCULPT_temp_customlayer_has function to check if a temporary customdata attribute layer exists. * Fixed a bunch of broken sliders in the paint_toolsystem_common.py.
This commit is contained in:
parent
673e1fbac5
commit
07be162dd5
|
@ -114,7 +114,6 @@ class DynamicPaintPanelGen:
|
|||
}
|
||||
|
||||
def callback():
|
||||
print("creating panel")
|
||||
DynamicPaintPanelGen.createPanel(group)
|
||||
pass
|
||||
|
||||
|
@ -353,11 +352,14 @@ class UnifiedPaintPanel:
|
|||
|
||||
|
||||
@staticmethod
|
||||
def channel_unified(layout, context, brush, prop_name, icon='NONE', pressure=None, text=None,
|
||||
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):
|
||||
""" Generalized way of adding brush options to the UI,
|
||||
along with their pen pressure setting and global toggle"""
|
||||
|
||||
if baselayout is None:
|
||||
baselayout = layout
|
||||
|
||||
if slider is None:
|
||||
slider = False
|
||||
|
||||
|
@ -527,6 +529,8 @@ class UnifiedPaintPanel:
|
|||
row.prop(ch, "ui_expanded", text="", icon="TRIA_DOWN" if ch.ui_expanded else "TRIA_RIGHT")
|
||||
|
||||
if ch.ui_expanded:
|
||||
layout = baselayout.column()
|
||||
|
||||
for i, mp in enumerate(ch.mappings):
|
||||
mp0 = mp
|
||||
if mp.inherit:
|
||||
|
@ -563,6 +567,12 @@ class UnifiedPaintPanel:
|
|||
props.shape = shape
|
||||
props.path = path2
|
||||
|
||||
col.prop(mp, "factor")
|
||||
col.prop(mp, "blendmode")
|
||||
row = col.row()
|
||||
row.prop(mp, "min")
|
||||
row.prop(mp, "max")
|
||||
|
||||
#row2.prop(mp, "curve")
|
||||
|
||||
return row
|
||||
|
@ -1341,12 +1351,12 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
|
||||
# Per sculpt tool options.
|
||||
|
||||
def doprop(col, prop, slider=None):
|
||||
def doprop(col, prop, slider=None, text=None, baselayout=None):
|
||||
UnifiedPaintPanel.channel_unified(col,
|
||||
context,
|
||||
brush,
|
||||
prop,
|
||||
slider=slider)
|
||||
slider=slider, text=text, baselayout=baselayout)
|
||||
|
||||
if sculpt_tool == "VCOL_BOUNDARY":
|
||||
row = layout.row()
|
||||
|
@ -1480,17 +1490,18 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
|
||||
elif sculpt_tool == 'SCRAPE':
|
||||
row = layout.row(align=True)
|
||||
doprop(row, "area_radius_factor")
|
||||
doprop(row, "use_pressure_area_radius", text="")
|
||||
doprop(row, "area_radius_factor", baselayout=layout)
|
||||
#doprop(row, "use_pressure_area_radius", text="",
|
||||
#baselayout=layout)
|
||||
row = layout.row()
|
||||
doprop(row, "invert_to_scrape_fill", text="Invert to Fill")
|
||||
doprop(row, "invert_to_scrape_fill", text="Invert to Fill", baselayout=layout)
|
||||
|
||||
elif sculpt_tool == 'FILL':
|
||||
row = layout.row(align=True)
|
||||
doprop(row, "area_radius_factor")
|
||||
doprop(row, "use_pressure_area_radius", text="")
|
||||
doprop(row, "area_radius_factor", baselayout=layout)
|
||||
#doprop(row, "use_pressure_area_radius", text="")
|
||||
row = layout.row()
|
||||
doprop(row, "invert_to_scrape_fill", text="Invert to Scrape")
|
||||
doprop(row, "invert_to_scrape_fill", text="Invert to Scrape", baselayout=layout)
|
||||
|
||||
elif sculpt_tool == 'GRAB':
|
||||
doprop(layout, "use_grab_active_vertex")
|
||||
|
@ -1499,33 +1510,31 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
|
||||
elif sculpt_tool == 'PAINT':
|
||||
row = layout.row(align=True)
|
||||
doprop(row, "flow")
|
||||
doprop(row, "invert_flow_pressure", text="")
|
||||
doprop(row, "use_flow_pressure", text="")
|
||||
doprop(row, "flow", baselayout=layout)
|
||||
row.prop(brush.channels["flow"].mappings["PRESSURE"], "invert", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(brush, "wet_mix")
|
||||
row.prop(brush, "invert_wet_mix_pressure", text="")
|
||||
row.prop(brush, "use_wet_mix_pressure", text="")
|
||||
doprop(row, "wet_mix", baselayout=layout)
|
||||
row.prop(brush.channels["wet_mix"].mappings["PRESSURE"], "invert", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
doprop(row, "wet_persistence")
|
||||
doprop(row, "invert_wet_persistence_pressure", text="")
|
||||
doprop(row, "use_wet_persistence_pressure", text="")
|
||||
doprop(row, "wet_persistence", baselayout=layout)
|
||||
row.prop(brush.channels["wet_persistence"].mappings["PRESSURE"], "invert", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
doprop(row, "wet_paint_radius_factor")
|
||||
doprop(row, "wet_paint_radius_factor", baselayout=layout)
|
||||
|
||||
row = layout.row(align=True)
|
||||
doprop(row, "density")
|
||||
doprop(row, "invert_density_pressure", text="")
|
||||
doprop(row, "use_density_pressure", text="")
|
||||
doprop(row, "density", baselayout=layout)
|
||||
row.prop(brush.channels["density"].mappings["PRESSURE"], "invert", text="")
|
||||
|
||||
row = layout.row()
|
||||
doprop(row, "tip_roundness")
|
||||
doprop(row, "tip_roundness", baselayout=layout)
|
||||
|
||||
row = layout.row()
|
||||
doprop(row, "tip_scale_x")
|
||||
doprop(row, "tip_scale_x", baselayout=layout)
|
||||
|
||||
doprop(layout.column(), "hue_offset", baselayout=layout)
|
||||
|
||||
elif sculpt_tool == 'SMEAR':
|
||||
col = layout.column()
|
||||
|
@ -1602,7 +1611,7 @@ def brush_settings(layout, context, brush, popover=False):
|
|||
doprop(col, "smear_deform_type")
|
||||
|
||||
elif sculpt_tool == 'MASK':
|
||||
doprop(layout.row(), "mask_tool", expand=True)
|
||||
doprop(layout.row(), "mask_tool", expand=True, baselayout=layout)
|
||||
|
||||
# End sculpt_tool interface.
|
||||
|
||||
|
@ -1813,6 +1822,7 @@ class ReorderBrushChannel(Operator):
|
|||
|
||||
return {'FINISHED'}
|
||||
|
||||
classes.append(ReorderBrushChannel)
|
||||
|
||||
def brush_settings_channels(layout, context, brush, ui_editing=False, popover=False, show_reorder=None, filterkey="show_in_workspace",
|
||||
parent="VIEW3D_PT_tools_brush_settings_channels", prefix="VIEW3D_PT_brush_category_"):
|
||||
|
|
|
@ -105,15 +105,16 @@ typedef struct BrushMappingDef {
|
|||
float min, max;
|
||||
int blendmode;
|
||||
float factor; // if 0, will default to 1.0
|
||||
bool no_default;
|
||||
} BrushMappingDef;
|
||||
|
||||
typedef struct BrushMappingPreset {
|
||||
// must match order of BRUSH_MAPPING_XXX enums
|
||||
struct BrushMappingDef pressure, xtilt, ytilt, angle, speed;
|
||||
struct BrushMappingDef pressure, xtilt, ytilt, angle, speed, random;
|
||||
} BrushMappingPreset;
|
||||
|
||||
typedef struct BrushMappingData {
|
||||
float pressure, xtilt, ytilt, angle, speed;
|
||||
float pressure, xtilt, ytilt, angle, speed, random;
|
||||
} BrushMappingData;
|
||||
|
||||
#define MAX_BRUSH_ENUM_DEF 32
|
||||
|
@ -227,6 +228,7 @@ bool BKE_brush_channelset_has(BrushChannelSet *chset, const char *idname);
|
|||
|
||||
BrushChannel *BKE_brush_channelset_add_builtin(BrushChannelSet *chset, const char *idname);
|
||||
BrushChannel *BKE_brush_channelset_ensure_builtin(BrushChannelSet *chset, const char *idname);
|
||||
void BKE_brush_mapping_reset(BrushChannel *ch, int tool, int mapping);
|
||||
|
||||
void BKE_brush_channelset_merge(BrushChannelSet *dst,
|
||||
BrushChannelSet *child,
|
||||
|
|
|
@ -302,6 +302,10 @@ MAKE_FLOAT_EX(rate, "Rate", "", 0.1f, 0.0001f, 10000.0f, 0.01f, 1.0f, false)
|
|||
MAKE_FLOAT(flow, "Flow", "Amount of paint that is applied per stroke sample", 1.0f, 0.0f, 1.0f)
|
||||
MAKE_FLOAT(wet_mix, "Wet Mix", "Amount of paint that is picked from the surface into the brush color", 0.0f, 0.0f, 1.0f)
|
||||
MAKE_FLOAT(wet_persistence, "Wet Persistence", "Amount of wet paint that stays in the brush after applying paint to the surface", 0.0f, 0.0f, 1.0f)
|
||||
MAKE_FLOAT_EX(hue_offset, "Hue", "Offset Applied To Hue", 0.5f, -3.0f, 3.0f, 0.0f, 1.0f, false)
|
||||
MAKE_FLOAT(wet_paint_radius_factor, "Wet Paint Radius",
|
||||
"Ratio between the brush radius and the radius that is going to be "
|
||||
"used to sample the color to blend in wet paint", 0.5f, 0.0f, 2.0f)
|
||||
MAKE_FLOAT(density, "Density", "Amount of random elements that are going to be affected by the brush", 1.0f, 0.0f, 1.0f)
|
||||
MAKE_FLOAT(tip_scale_x, "Tip Scale X", "Scale of the brush tip in the X axis", 1.0f, 0.0f, 1.0f)
|
||||
MAKE_FLOAT(dash_ratio, "Dash Ratio", "Ratio of samples in a cycle that the brush is enabled", 1.0f, 0.0f, 1.0f)
|
||||
|
|
|
@ -416,14 +416,14 @@ void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
|||
|
||||
BrushMappingDef *mdef = (&def->mappings.pressure) + i;
|
||||
|
||||
if (mdef->min != mdef->max) {
|
||||
min = mdef->min;
|
||||
max = mdef->max;
|
||||
}
|
||||
else {
|
||||
if (!mdef->no_default) {
|
||||
min = 0.0f;
|
||||
max = 1.0f;
|
||||
}
|
||||
else {
|
||||
min = mdef->min;
|
||||
max = mdef->max;
|
||||
}
|
||||
|
||||
if (mdef->inv) {
|
||||
mp->flag |= BRUSH_MAPPING_INVERT;
|
||||
|
@ -431,20 +431,22 @@ void BKE_brush_channel_init(BrushChannel *ch, BrushChannelType *def)
|
|||
|
||||
int slope = CURVEMAP_SLOPE_POSITIVE;
|
||||
|
||||
BKE_curvemapping_set_defaults(curve, 1, 0, min, 1, max);
|
||||
BKE_curvemapping_set_defaults(curve, 1, 0, 0.0f, 1, 1.0f);
|
||||
|
||||
for (int j = 0; j < 1; j++) {
|
||||
BKE_curvemap_reset(&curve->cm[j],
|
||||
&(struct rctf){.xmin = 0, .ymin = min, .xmax = 1, .ymax = max},
|
||||
&(struct rctf){.xmin = 0.0f, .ymin = 0.0f, .xmax = 1.0f, .ymax = 1.0f},
|
||||
mdef->curve,
|
||||
slope);
|
||||
}
|
||||
|
||||
BKE_curvemapping_init(curve);
|
||||
|
||||
mp->min = min;
|
||||
mp->max = max;
|
||||
mp->curve = GET_CACHE_CURVE(curve); // frees curve and returns cached copy
|
||||
|
||||
mp->blendmode = mdef->blendmode;
|
||||
mp->blendmode = !mdef->no_default ? MA_RAMP_MULT : mdef->blendmode;
|
||||
mp->factor = mdef->factor == 0.0f ? 1.0f : mdef->factor;
|
||||
|
||||
if (mdef->enabled) {
|
||||
|
@ -923,7 +925,7 @@ static bool channel_has_mappings(BrushChannel *ch)
|
|||
return false;
|
||||
}
|
||||
|
||||
// idx is used by vector channels
|
||||
/* idx is used by vector channels */
|
||||
double BKE_brush_channel_eval_mappings(BrushChannel *ch,
|
||||
BrushMappingData *mapdata,
|
||||
double f,
|
||||
|
@ -935,7 +937,7 @@ double BKE_brush_channel_eval_mappings(BrushChannel *ch,
|
|||
}
|
||||
|
||||
if (mapdata) {
|
||||
double factor = 1.0f;
|
||||
double factor = f; // 1.0f;
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BrushMapping *mp = ch->mappings + i;
|
||||
|
@ -951,7 +953,10 @@ double BKE_brush_channel_eval_mappings(BrushChannel *ch,
|
|||
}
|
||||
|
||||
double f2 = (float)BKE_curvemapping_evaluateF(mp->curve, 0, inputf);
|
||||
f2 = mp->min + (mp->max - mp->min) * f2;
|
||||
|
||||
/* make sure to update blend_items in rna_brush_engine.c
|
||||
when adding new mode implementations */
|
||||
switch (mp->blendmode) {
|
||||
case MA_RAMP_BLEND:
|
||||
break;
|
||||
|
@ -959,7 +964,7 @@ double BKE_brush_channel_eval_mappings(BrushChannel *ch,
|
|||
f2 *= factor;
|
||||
break;
|
||||
case MA_RAMP_DIV:
|
||||
f2 = factor / (0.00001f + f2);
|
||||
f2 = factor / (f2 == 0.0f ? 0.0001f : f2);
|
||||
break;
|
||||
case MA_RAMP_ADD:
|
||||
f2 += factor;
|
||||
|
@ -980,7 +985,9 @@ double BKE_brush_channel_eval_mappings(BrushChannel *ch,
|
|||
factor += (f2 - factor) * mp->factor;
|
||||
}
|
||||
|
||||
f *= factor;
|
||||
f = factor;
|
||||
CLAMP(f, ch->def->min, ch->def->max);
|
||||
// f *= factor;
|
||||
}
|
||||
|
||||
return f;
|
||||
|
@ -1767,6 +1774,10 @@ void BKE_brush_channelset_read(BlendDataReader *reader, BrushChannelSet *chset)
|
|||
|
||||
CurveMapping *curve = mp->curve;
|
||||
|
||||
if (mp->min == mp->max == 0.0f) {
|
||||
mp->max = 1.0f;
|
||||
}
|
||||
|
||||
if (curve) {
|
||||
BKE_curvemapping_blend_read(reader, curve);
|
||||
BKE_curvemapping_init(curve);
|
||||
|
@ -1833,6 +1844,8 @@ const char *BKE_brush_mapping_type_to_str(BrushMappingType mapping)
|
|||
return "X Tilt";
|
||||
case BRUSH_MAPPING_YTILT:
|
||||
return "Y Tilt";
|
||||
case BRUSH_MAPPING_RANDOM:
|
||||
return "Random";
|
||||
case BRUSH_MAPPING_MAX:
|
||||
return "Error";
|
||||
}
|
||||
|
@ -1853,6 +1866,8 @@ const char *BKE_brush_mapping_type_to_typename(BrushMappingType mapping)
|
|||
return "XTILT";
|
||||
case BRUSH_MAPPING_YTILT:
|
||||
return "YTILT";
|
||||
case BRUSH_MAPPING_RANDOM:
|
||||
return "RANDOM";
|
||||
case BRUSH_MAPPING_MAX:
|
||||
return "Error";
|
||||
}
|
||||
|
@ -1876,6 +1891,9 @@ void BKE_brush_mapping_copy_data(BrushMapping *dst, BrushMapping *src)
|
|||
}
|
||||
|
||||
dst->blendmode = src->blendmode;
|
||||
|
||||
dst->min = src->min;
|
||||
dst->max = src->max;
|
||||
dst->factor = src->factor;
|
||||
dst->flag = src->flag;
|
||||
dst->input_channel = src->input_channel;
|
||||
|
|
|
@ -94,7 +94,8 @@ To enable converting to/from old data:
|
|||
.type = BRUSH_CHANNEL_TYPE_FLOAT,\
|
||||
.subtype = BRUSH_CHANNEL_FACTOR,\
|
||||
.mappings = {\
|
||||
.pressure = {.curve = CURVE_PRESET_LINE, .factor = 1.0f, .min = 0.0f, .max = 1.0f, .enabled = pressure_enabled, .inv = pressure_inv},\
|
||||
.pressure = {.curve = CURVE_PRESET_LINE, .factor = 1.0f, .no_default=true, .blendmode = MA_RAMP_MULT, \
|
||||
.min = 0.0f, .max = 1.0f, .enabled = pressure_enabled, .inv = pressure_inv},\
|
||||
}\
|
||||
},
|
||||
#define MAKE_FLOAT_EX(idname1, name1, tooltip1, value1, min1, max1, smin1, smax1, pressure_enabled)\
|
||||
|
@ -237,6 +238,8 @@ static BrushChannelType *_get_def(const char *idname)
|
|||
static bool do_builtin_init = true;
|
||||
static bool check_builtin_init()
|
||||
{
|
||||
BrushChannelType *def;
|
||||
|
||||
if (!do_builtin_init || !BLI_thread_is_main()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -259,11 +262,23 @@ static bool check_builtin_init()
|
|||
SUBTYPE_SET(autosmooth_radius_scale, BRUSH_CHANNEL_PERCENT);
|
||||
SUBTYPE_SET(topology_rake_radius_scale, BRUSH_CHANNEL_PERCENT);
|
||||
|
||||
def = GETDEF(hue_offset);
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
BrushMappingDef *mdef = (&def->mappings.pressure) + i;
|
||||
|
||||
mdef->no_default = true;
|
||||
mdef->curve = CURVE_PRESET_LINE;
|
||||
mdef->min = i == 0 ? 0.0f : -1.0f; /* have pressure use minimum of 0.0f */
|
||||
mdef->max = 1.0f;
|
||||
mdef->factor = 0.5f;
|
||||
mdef->blendmode = MA_RAMP_ADD;
|
||||
}
|
||||
|
||||
SETCAT(concave_mask_factor, "Automasking");
|
||||
SETCAT(automasking, "Automasking");
|
||||
SETCAT(automasking_boundary_edges_propagation_steps, "Automasking");
|
||||
|
||||
BrushChannelType *def = GETDEF(concave_mask_factor);
|
||||
def = GETDEF(concave_mask_factor);
|
||||
def->mappings.pressure.inv = true;
|
||||
|
||||
// don't group strength/radius/direction in subpanels
|
||||
|
@ -349,9 +364,11 @@ static bool check_builtin_init()
|
|||
SETCAT(secondary_color, "Color");
|
||||
SETCAT(blend, "Color");
|
||||
SETCAT(wet_mix, "Color");
|
||||
SETCAT(hue_offset, "Color");
|
||||
SETCAT(wet_persistence, "Color");
|
||||
SETCAT(density, "Color");
|
||||
SETCAT(flow, "Color");
|
||||
SETCAT(wet_paint_radius_factor, "Color");
|
||||
|
||||
SETCAT(vcol_boundary_spacing, "Color Boundary Hardening");
|
||||
SETCAT(vcol_boundary_radius_scale, "Color Boundary Hardening");
|
||||
|
@ -435,6 +452,7 @@ static BrushSettingsMap brush_settings_map[] = {
|
|||
DEF(flow, flow, FLOAT, FLOAT)
|
||||
DEF(hardness, hardness, FLOAT, FLOAT)
|
||||
DEF(wet_mix, wet_mix, FLOAT, FLOAT)
|
||||
DEF(wet_paint_radius_factor, wet_paint_radius_factor, FLOAT, FLOAT)
|
||||
DEF(wet_persistence, wet_persistence, FLOAT, FLOAT)
|
||||
DEF(density, density, FLOAT, FLOAT)
|
||||
DEF(tip_scale_x, tip_scale_x, FLOAT, FLOAT)
|
||||
|
@ -919,6 +937,7 @@ void BKE_brush_channelset_compat_load(BrushChannelSet *chset, Brush *brush, bool
|
|||
}
|
||||
}
|
||||
|
||||
/* todo: move into BKE_brush_reset_mapping*/
|
||||
void reset_clay_mappings(BrushChannelSet *chset, bool strips)
|
||||
{
|
||||
BrushMapping *mp = BRUSHSET_LOOKUP(chset, radius)->mappings + BRUSH_MAPPING_PRESSURE;
|
||||
|
@ -1136,6 +1155,8 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
ADDCH(color);
|
||||
ADDCH(secondary_color);
|
||||
ADDCH(wet_mix);
|
||||
ADDCH(hue_offset);
|
||||
ADDCH(wet_paint_radius_factor);
|
||||
ADDCH(wet_persistence);
|
||||
ADDCH(density);
|
||||
ADDCH(tip_scale_x);
|
||||
|
@ -1470,6 +1491,8 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
|
||||
SHOWWRK(secondary_color);
|
||||
SHOWWRK(wet_mix);
|
||||
SHOWWRK(hue_offset);
|
||||
SHOWWRK(wet_paint_radius_factor);
|
||||
SHOWWRK(wet_persistence);
|
||||
SHOWWRK(density);
|
||||
SHOWWRK(tip_scale_x);
|
||||
|
@ -1518,6 +1541,35 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
#undef SHOWPROPS
|
||||
namestack_pop();
|
||||
}
|
||||
|
||||
void BKE_brush_mapping_reset(BrushChannel *ch, int tool, int mapping)
|
||||
{
|
||||
BrushMapping *mp = ch->mappings + mapping;
|
||||
BrushMappingDef *mdef = (&ch->def->mappings.pressure) + mapping;
|
||||
|
||||
BKE_brush_mapping_ensure_write(mp);
|
||||
|
||||
CurveMapping *curve = mp->curve;
|
||||
|
||||
BKE_curvemapping_set_defaults(curve, 1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
BKE_curvemap_reset(
|
||||
curve->cm, &(struct rctf){.xmin = 0, .ymin = 0.0, .xmax = 1.0, .ymax = 1.0}, mdef->curve, 1);
|
||||
BKE_curvemapping_init(curve);
|
||||
|
||||
if (STREQ(ch->idname, "hue_offset") && mapping == BRUSH_MAPPING_PRESSURE) {
|
||||
CurveMap *cuma = curve->cm;
|
||||
cuma->curve[0].x = 0.0f;
|
||||
cuma->curve[0].y = 0.0f;
|
||||
|
||||
cuma->curve[1].x = 1.0f;
|
||||
cuma->curve[1].y = 1.0f;
|
||||
|
||||
BKE_curvemap_insert(cuma, 0.65f, 0.0f);
|
||||
cuma->curve[1].flag |= CUMA_HANDLE_VECTOR;
|
||||
}
|
||||
|
||||
BKE_curvemapping_changed(curve, true);
|
||||
}
|
||||
void BKE_brush_builtin_create(Brush *brush, int tool)
|
||||
{
|
||||
namestack_push(__func__);
|
||||
|
@ -1622,13 +1674,17 @@ void BKE_brush_builtin_create(Brush *brush, int tool)
|
|||
GETCH(dyntopo_disabled)->ivalue = 1;
|
||||
GETCH(slide_deform_type)->ivalue = BRUSH_SLIDE_DEFORM_DRAG;
|
||||
break;
|
||||
case SCULPT_TOOL_PAINT:
|
||||
case SCULPT_TOOL_PAINT: {
|
||||
BRUSHSET_SET_BOOL(chset, dyntopo_disabled, true);
|
||||
BRUSHSET_SET_FLOAT(chset, hardness, 0.4f);
|
||||
BRUSHSET_SET_FLOAT(chset, spacing, 10.0f);
|
||||
BRUSHSET_SET_FLOAT(chset, strength, 0.6f);
|
||||
BRUSHSET_LOOKUP(chset, strength)->flag &= ~BRUSH_MAPPING_INHERIT;
|
||||
|
||||
BrushChannel *ch = BRUSHSET_LOOKUP(chset, hue_offset);
|
||||
BKE_brush_mapping_reset(ch, SCULPT_TOOL_PAINT, BRUSH_MAPPING_PRESSURE);
|
||||
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;
|
||||
|
|
|
@ -1893,6 +1893,40 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_ATLEAST(bmain, 300, 37)) {
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (!brush->channels) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BrushChannel *ch;
|
||||
ch = BRUSHSET_LOOKUP(brush->channels, hue_offset);
|
||||
|
||||
if (ch) {
|
||||
BKE_brush_mapping_reset(ch, brush->sculpt_tool, BRUSH_MAPPING_PRESSURE);
|
||||
}
|
||||
|
||||
ch = (BrushChannel *)brush->channels->channels.first;
|
||||
for (; ch; ch = ch->next) {
|
||||
if (!ch->mappings[BRUSH_MAPPING_RANDOM].factor) {
|
||||
ch->mappings[BRUSH_MAPPING_RANDOM].factor = 1.0f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BRUSH_MAPPING_MAX; i++) {
|
||||
if (ch->mappings[i].blendmode == MA_RAMP_BLEND) {
|
||||
ch->mappings[i].blendmode = MA_RAMP_MULT;
|
||||
}
|
||||
|
||||
if (ch->mappings[i].min == ch->mappings[i].max) {
|
||||
ch->mappings[i].min = 0.0f;
|
||||
ch->mappings[i].max = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Versioning code until next subversion bump goes here.
|
||||
*
|
||||
|
|
|
@ -853,9 +853,48 @@ bool SCULPT_temp_customlayer_ensure(SculptSession *ss,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: thoroughly test this function */
|
||||
bool SCULPT_temp_customlayer_has(SculptSession *ss,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name)
|
||||
{
|
||||
CustomData *vdata = NULL, *pdata = NULL, *data = NULL;
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_BMESH:
|
||||
vdata = &ss->bm->vdata;
|
||||
pdata = &ss->bm->pdata;
|
||||
break;
|
||||
case PBVH_FACES:
|
||||
pdata = ss->pdata;
|
||||
vdata = ss->vdata;
|
||||
break;
|
||||
case PBVH_GRIDS:
|
||||
pdata = ss->pdata;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
data = vdata;
|
||||
break;
|
||||
case ATTR_DOMAIN_FACE:
|
||||
data = pdata;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
return CustomData_get_named_layer_index(data, proptype, name) >= 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SCULPT_temp_customlayer_release(SculptSession *ss, SculptCustomLayer *scl)
|
||||
{
|
||||
int proptype = scl->proptype;
|
||||
AttributeDomain domain = scl->domain;
|
||||
|
||||
if (scl->released) {
|
||||
|
@ -1694,8 +1733,6 @@ static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(const SculptSessi
|
|||
|
||||
bool SCULPT_vertex_has_unique_face_set(const SculptSession *ss, SculptVertRef vertex)
|
||||
{
|
||||
MSculptVert *mv = SCULPT_vertex_get_mdyntopo(ss, vertex);
|
||||
|
||||
return !SCULPT_vertex_is_boundary(ss, vertex, SCULPT_BOUNDARY_FACE_SET);
|
||||
}
|
||||
|
||||
|
@ -1906,8 +1943,6 @@ static void sculpt_vertex_neighbors_get_faces(const SculptSession *ss,
|
|||
|
||||
if (ok) {
|
||||
for (int j = 0; j < 2; j += 1) {
|
||||
int e = 0;
|
||||
|
||||
if (f_adj_v[j] != index) {
|
||||
sculpt_vertex_neighbor_add(
|
||||
iter, BKE_pbvh_make_vref(f_adj_v[j]), BKE_pbvh_make_eref(j ? e2 : e1), f_adj_v[j]);
|
||||
|
@ -2085,7 +2120,6 @@ static bool neighbor_cache_begin(const SculptSession *ss)
|
|||
}
|
||||
|
||||
ncache->totvert = totvert;
|
||||
NeighborCache *old = ss->cache->ncache;
|
||||
|
||||
atomic_cas_ptr((void **)&ss->cache->ncache, NULL, ncache);
|
||||
|
||||
|
@ -2413,7 +2447,6 @@ SculptCornerType SCULPT_vertex_is_corner(const SculptSession *ss,
|
|||
const SculptVertRef vertex,
|
||||
SculptCornerType cornertype)
|
||||
{
|
||||
bool check_facesets = cornertype & SCULPT_CORNER_FACE_SET;
|
||||
SculptCornerType ret = 0;
|
||||
MSculptVert *mv = NULL;
|
||||
|
||||
|
@ -2473,7 +2506,6 @@ SculptBoundaryType SCULPT_vertex_is_boundary(const SculptSession *ss,
|
|||
const SculptVertRef vertex,
|
||||
SculptBoundaryType boundary_types)
|
||||
{
|
||||
bool check_facesets = boundary_types & SCULPT_BOUNDARY_FACE_SET;
|
||||
MSculptVert *mv = NULL;
|
||||
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
|
@ -3195,7 +3227,6 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
|
|||
}
|
||||
|
||||
PBVHVertexIter vd;
|
||||
SculptOrigVertData orig_data;
|
||||
|
||||
bool modified = false;
|
||||
|
||||
|
@ -4044,7 +4075,6 @@ static float brush_strength(const Sculpt *sd,
|
|||
const float feather,
|
||||
const UnifiedPaintSettings *ups)
|
||||
{
|
||||
const Scene *scene = cache->vc->scene;
|
||||
const Brush *brush = cache->brush; // BKE_paint_brush((Paint *)&sd->paint);
|
||||
|
||||
/* Primary strength input; square it to make lower values more sensitive. */
|
||||
|
@ -5479,11 +5509,8 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
|
|||
const float *offset = data->offset;
|
||||
|
||||
PBVHVertexIter vd;
|
||||
SculptOrigVertData orig_data;
|
||||
float(*proxy)[3];
|
||||
|
||||
// SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
|
||||
|
||||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
|
@ -5499,13 +5526,13 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
|
|||
normalize_v3(noffset);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
// SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
SCULPT_vertex_check_origdata(ss, vd.vertex);
|
||||
MSculptVert *mv = SCULPT_vertex_get_mdyntopo(ss, vd.vertex);
|
||||
|
||||
if (!sculpt_brush_test_sq_fn(&test, mv->origco)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Offset vertex. */
|
||||
const float fade = SCULPT_brush_strength_factor(ss,
|
||||
brush,
|
||||
|
@ -5538,7 +5565,6 @@ static void do_draw_sharp_brush_task_cb_ex_plane(void *__restrict userdata,
|
|||
const float *offset = data->offset;
|
||||
|
||||
PBVHVertexIter vd;
|
||||
SculptOrigVertData orig_data;
|
||||
float(*proxy)[3];
|
||||
|
||||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
@ -5662,8 +5688,6 @@ static void sculpt_stroke_cache_snap_context_init(bContext *C, Object *ob)
|
|||
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
cache->snap_context = ED_transform_snap_object_context_create(scene, 0);
|
||||
cache->depsgraph = depsgraph;
|
||||
|
@ -6491,7 +6515,6 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
|
|||
const bool grab_silhouette = brush->flag2 & BRUSH_GRAB_SILHOUETTE;
|
||||
const bool use_geodesic_dists = brush->flag2 & BRUSH_USE_SURFACE_FALLOFF;
|
||||
|
||||
int i = 0;
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
|
||||
|
@ -7304,7 +7327,6 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
|
|||
vd.vertex,
|
||||
thread_id);
|
||||
|
||||
const int vi = vd.index;
|
||||
float *disp_factor;
|
||||
|
||||
if (use_persistent_base) {
|
||||
|
@ -9687,9 +9709,6 @@ static void get_nodes_undo(Sculpt *sd,
|
|||
BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings);
|
||||
}
|
||||
|
||||
Brush *oldbrush = ss->cache->brush;
|
||||
Brush _dummy = *brush, *brush2 = &_dummy;
|
||||
|
||||
if (ss->cache->original) {
|
||||
SculptThreadedTaskData task_data = {
|
||||
.sd = sd,
|
||||
|
@ -9743,8 +9762,6 @@ static void SCULPT_run_command(
|
|||
brush2->curve = ch->curve.curve;
|
||||
}
|
||||
|
||||
const bool use_original = sculpt_tool_needs_original(cmd->tool) ? true : ss->cache->original;
|
||||
|
||||
// Load parameters into brush2 for compatibility with old code
|
||||
// Make sure to remove all pen pressure/tilt old code
|
||||
BKE_brush_channelset_compat_load(cmd->params_mapped, brush2, false);
|
||||
|
@ -9999,8 +10016,8 @@ static void SCULPT_run_commandlist(
|
|||
BRUSHSET_SET_FLOAT(ss->cache->channels_final, projection, projection);
|
||||
}
|
||||
|
||||
int totnode;
|
||||
PBVHNode **nodes;
|
||||
int totnode = 0;
|
||||
PBVHNode **nodes = NULL;
|
||||
|
||||
float start_radius = ss->cache->radius;
|
||||
|
||||
|
@ -11369,6 +11386,8 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
|
|||
// printf("pressure: %f\n", cache->pressure);
|
||||
}
|
||||
|
||||
cache->input_mapping.random = BLI_thread_frand(0);
|
||||
|
||||
cache->x_tilt = RNA_float_get(ptr, "x_tilt");
|
||||
cache->y_tilt = RNA_float_get(ptr, "y_tilt");
|
||||
cache->input_mapping.xtilt = cache->x_tilt;
|
||||
|
@ -11391,7 +11410,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
|
|||
direction[3] = 0.0f;
|
||||
mul_v4_m4v4(direction, cache->projection_mat, direction);
|
||||
|
||||
cache->input_mapping.angle = atan2(direction[1], direction[0]);
|
||||
cache->input_mapping.angle = (atan2(direction[1], direction[0]) / (float)M_PI) * 0.5 + 0.5;
|
||||
|
||||
// cache->vc
|
||||
}
|
||||
|
@ -12624,8 +12643,6 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
|
||||
SculptCustomLayer *scl_co, *scl_no, *scl_disp;
|
||||
|
||||
SculptLayerParams params = {.permanent = true, .simple_array = false};
|
||||
|
||||
SCULPT_ensure_persistent_layers(ss);
|
||||
|
||||
scl_co = ss->custom_layers[SCULPT_SCL_PERS_CO];
|
||||
|
@ -14593,7 +14610,6 @@ int SCULPT_vertex_valence_get(const struct SculptSession *ss, SculptVertRef vert
|
|||
{
|
||||
SculptVertexNeighborIter ni;
|
||||
int tot = 0;
|
||||
int mval = -1;
|
||||
|
||||
#if 0
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
|
||||
|
|
|
@ -1171,6 +1171,7 @@ typedef struct UVSmoothVert {
|
|||
BMLoop *ls[MAXUVLOOPS];
|
||||
struct UVSmoothVert *neighbors[MAXUVNEIGHBORS];
|
||||
int totloop, totneighbor;
|
||||
float brushfade;
|
||||
} UVSmoothVert;
|
||||
|
||||
typedef struct UVSmoothTri {
|
||||
|
@ -1205,6 +1206,7 @@ typedef struct UVSolver {
|
|||
double totarea2d;
|
||||
|
||||
double strength;
|
||||
int cd_sculpt_vert;
|
||||
} UVSolver;
|
||||
|
||||
/*that that currently this tool is *not* threaded*/
|
||||
|
@ -1255,7 +1257,16 @@ void *uvsolver_calc_loop_key(UVSolver *solver, BMLoop *l)
|
|||
|
||||
intptr_t x = (intptr_t)(uv->uv[0] * 16384.0);
|
||||
intptr_t y = (intptr_t)(uv->uv[1] * 16384.0);
|
||||
intptr_t key = y * 16384LL + x;
|
||||
intptr_t key;
|
||||
MSculptVert *mv = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->v);
|
||||
|
||||
if ((mv->flag & SCULPTVERT_SEAM_BOUNDARY) ||
|
||||
(l->e->head.hflag | l->prev->e->head.hflag) & BM_ELEM_SEAM) {
|
||||
key = y * 16384LL + x;
|
||||
}
|
||||
else {
|
||||
key = (intptr_t)l->v;
|
||||
}
|
||||
|
||||
return POINTER_FROM_INT(key);
|
||||
}
|
||||
|
@ -1272,10 +1283,26 @@ static UVSmoothVert *uvsolver_get_vert(UVSolver *solver, BMLoop *l)
|
|||
v = BLI_mempool_alloc(solver->verts);
|
||||
memset(v, 0, sizeof(*v));
|
||||
|
||||
MSculptVert *mv = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->v);
|
||||
MSculptVert *mv2 = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->prev->v);
|
||||
MSculptVert *mv3 = BKE_PBVH_SCULPTVERT(solver->cd_sculpt_vert, l->next->v);
|
||||
|
||||
v->boundary = mv->flag & SCULPTVERT_SEAM_BOUNDARY;
|
||||
if ((mv->flag | mv2->flag | mv3->flag) & SCULPTVERT_SHARP_CORNER) {
|
||||
v->pinned = true;
|
||||
}
|
||||
|
||||
// copy_v2_v2(v->uv, uv->uv);
|
||||
v->uv[0] = (double)uv->uv[0];
|
||||
v->uv[1] = (double)uv->uv[1];
|
||||
|
||||
if (isnan(v->uv[0]) || !isfinite(v->uv[0])) {
|
||||
v->uv[0] = 0.0f;
|
||||
}
|
||||
if (isnan(v->uv[1]) || !isfinite(v->uv[1])) {
|
||||
v->uv[1] = 0.0f;
|
||||
}
|
||||
|
||||
copy_v3_v3(v->co, l->v->co);
|
||||
v->v = l->v;
|
||||
|
||||
|
@ -1509,9 +1536,12 @@ BLI_INLINE float uvsolver_vert_weight(UVSmoothVert *sv)
|
|||
{
|
||||
double w = 1.0;
|
||||
|
||||
if (sv->pinned || sv->boundary) {
|
||||
if (sv->pinned || sv->boundary || sv->brushfade == 0.0f) {
|
||||
w = 100000.0;
|
||||
}
|
||||
else {
|
||||
return 1.0 / sv->brushfade;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
@ -1642,7 +1672,7 @@ static float uvsolver_solve_step(UVSolver *solver)
|
|||
|
||||
sv->uv[j] = orig;
|
||||
|
||||
totw += 1.0 / uvsolver_vert_weight(sv);
|
||||
totw += uvsolver_vert_weight(sv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1651,14 +1681,23 @@ static float uvsolver_solve_step(UVSolver *solver)
|
|||
}
|
||||
|
||||
r1 *= -solver->strength * 0.75 * con->k / totg;
|
||||
// totw = 1.0 / totw;
|
||||
|
||||
if (totw == 0.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
totw = 1.0 / totw;
|
||||
|
||||
for (int i = 0; i < con->totvert; i++) {
|
||||
UVSmoothVert *sv = con->vs[i];
|
||||
double w = 1.0 / (uvsolver_vert_weight(sv) * totw);
|
||||
double w = uvsolver_vert_weight(sv) * totw * sv->brushfade;
|
||||
w = MIN2(w, 1.0);
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
sv->uv[j] += r1 * con->gs[i][j] * w;
|
||||
double off = r1 * con->gs[i][j] * w;
|
||||
|
||||
CLAMP(off, -0.1, 0.1);
|
||||
sv->uv[j] += off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1815,7 +1854,7 @@ static void sculpt_uv_brush_cb(void *__restrict userdata,
|
|||
void SCULPT_uv_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
Brush *brush = ss->cache ? ss->cache->brush : BKE_paint_brush(&sd->paint);
|
||||
float offset[3];
|
||||
const float bstrength = ss->cache->bstrength;
|
||||
|
||||
|
@ -1835,6 +1874,7 @@ void SCULPT_uv_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
|||
BKE_curvemapping_init(brush->curve);
|
||||
|
||||
UVSolver *solver = uvsolver_new(cd_uv);
|
||||
solver->cd_sculpt_vert = ss->cd_sculpt_vert;
|
||||
solver->strength = ss->cache->bstrength;
|
||||
|
||||
/* Threaded loop over nodes. */
|
||||
|
@ -1855,6 +1895,31 @@ void SCULPT_uv_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
|||
|
||||
uvsolver_solve_begin(solver);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, brush->falloff_shape);
|
||||
|
||||
BLI_mempool_iter iter;
|
||||
BLI_mempool_iternew(solver->verts, &iter);
|
||||
UVSmoothVert *sv = BLI_mempool_iterstep(&iter);
|
||||
|
||||
for (; sv; sv = BLI_mempool_iterstep(&iter)) {
|
||||
if (!sculpt_brush_test_sq_fn(&test, sv->v->co)) {
|
||||
sv->brushfade = 0.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
sv->brushfade = SCULPT_brush_strength_factor(ss,
|
||||
brush,
|
||||
sv->v->co,
|
||||
sqrtf(test.dist),
|
||||
NULL,
|
||||
sv->v->no,
|
||||
0.0f,
|
||||
(SculptVertRef){.i = (intptr_t)sv->v},
|
||||
0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
uvsolver_solve_step(solver);
|
||||
}
|
||||
|
|
|
@ -1014,6 +1014,7 @@ typedef struct SculptThreadedTaskData {
|
|||
bool any_vertex_sampled;
|
||||
|
||||
float *wet_mix_sampled_color;
|
||||
float hue_offset;
|
||||
|
||||
float *prev_mask;
|
||||
float *new_mask;
|
||||
|
@ -1933,6 +1934,10 @@ bool SCULPT_temp_customlayer_get(SculptSession *ss,
|
|||
SculptCustomLayer *scl,
|
||||
SculptLayerParams *params);
|
||||
bool SCULPT_temp_customlayer_release(SculptSession *ss, SculptCustomLayer *scl);
|
||||
bool SCULPT_temp_customlayer_has(SculptSession *ss,
|
||||
AttributeDomain domain,
|
||||
int proptype,
|
||||
const char *name);
|
||||
|
||||
bool SCULPT_dyntopo_automasking_init(const SculptSession *ss,
|
||||
Sculpt *sd,
|
||||
|
|
|
@ -119,6 +119,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
SculptSession *ss = data->ob->sculpt;
|
||||
const Brush *brush = data->brush;
|
||||
const float bstrength = fabsf(ss->cache->bstrength);
|
||||
float hue_offset = data->hue_offset;
|
||||
|
||||
const SculptCustomLayer *buffer_scl = data->scl;
|
||||
const SculptCustomLayer *stroke_id_scl = data->scl2;
|
||||
|
@ -139,6 +140,18 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
|
||||
IMB_colormanagement_srgb_to_scene_linear_v3(brush_color);
|
||||
|
||||
if (hue_offset != 0.5f) {
|
||||
hue_offset = (hue_offset * 2.0 - 1.0) * 0.5f;
|
||||
float hsv[3];
|
||||
|
||||
rgb_to_hsv_v(brush_color, hsv);
|
||||
|
||||
hsv[0] += hue_offset;
|
||||
hsv[0] -= floorf(hsv[0]);
|
||||
|
||||
hsv_to_rgb_v(hsv, brush_color);
|
||||
}
|
||||
|
||||
/* get un-pressure-mapped alpha */
|
||||
float alpha = BKE_brush_channelset_get_final_float(
|
||||
BKE_paint_brush(&data->sd->paint)->channels, data->sd->channels, "strength", NULL);
|
||||
|
@ -349,6 +362,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
.sd = sd,
|
||||
.ob = ob,
|
||||
.nodes = nodes,
|
||||
.hue_offset = SCULPT_get_float(ss, hue_offset, sd, brush),
|
||||
.brush = brush,
|
||||
.brush_color = brush_color,
|
||||
};
|
||||
|
@ -407,6 +421,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
.nodes = nodes,
|
||||
.wet_mix_sampled_color = wet_color,
|
||||
.mat = mat,
|
||||
.hue_offset = SCULPT_get_float(ss, hue_offset, sd, brush),
|
||||
.scl = &buffer_scl,
|
||||
.scl2 = &stroke_id_scl,
|
||||
.brush_color = brush_color,
|
||||
|
@ -530,6 +545,7 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
|
||||
SculptCustomLayer prev_scl;
|
||||
SculptLayerParams params = {.permanent = false, .simple_array = false};
|
||||
|
||||
SCULPT_temp_customlayer_ensure(
|
||||
ss, ATTR_DOMAIN_POINT, CD_PROP_COLOR, "_sculpt_smear_previous", ¶ms);
|
||||
SCULPT_temp_customlayer_get(
|
||||
|
@ -537,19 +553,6 @@ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
|
|||
|
||||
SCULPT_vertex_random_access_ensure(ss);
|
||||
|
||||
const int totvert = SCULPT_vertex_count_get(ss);
|
||||
|
||||
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
|
||||
if (!ss->cache->prev_colors) {
|
||||
ss->cache->prev_colors = MEM_callocN(sizeof(float[4]) * totvert, "prev colors");
|
||||
for (int i = 0; i < totvert; i++) {
|
||||
SculptVertRef vertex = BKE_pbvh_table_index_to_vertex(ss->pbvh, i);
|
||||
|
||||
copy_v4_v4(ss->cache->prev_colors[i], SCULPT_vertex_color_get(ss, vertex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BKE_curvemapping_init(brush->curve);
|
||||
|
||||
SculptThreadedTaskData data = {
|
||||
|
|
|
@ -38,6 +38,8 @@ typedef struct BrushMapping {
|
|||
short blendmode;
|
||||
short input_channel;
|
||||
int flag, type;
|
||||
|
||||
float min, max;
|
||||
} BrushMapping;
|
||||
|
||||
typedef struct BrushCurve {
|
||||
|
@ -59,7 +61,7 @@ typedef struct BrushChannel {
|
|||
float vector[4];
|
||||
BrushCurve curve;
|
||||
|
||||
BrushMapping mappings[5]; // should always be BRUSH_MAPPING_MAX
|
||||
BrushMapping mappings[6]; // should always be BRUSH_MAPPING_MAX
|
||||
|
||||
short type, ui_order;
|
||||
int flag;
|
||||
|
@ -88,7 +90,8 @@ typedef enum {
|
|||
BRUSH_MAPPING_YTILT = 2,
|
||||
BRUSH_MAPPING_ANGLE = 3,
|
||||
BRUSH_MAPPING_SPEED = 4,
|
||||
BRUSH_MAPPING_MAX = 5 // see BrushChannel.mappings
|
||||
BRUSH_MAPPING_RANDOM = 5,
|
||||
BRUSH_MAPPING_MAX = 6 // see BrushChannel.mappings
|
||||
} BrushMappingType;
|
||||
|
||||
#ifndef __GNUC__
|
||||
|
|
|
@ -646,6 +646,7 @@ static EnumPropertyItem mapping_type_items[] = {
|
|||
{BRUSH_MAPPING_YTILT, "YTILT", ICON_NONE, "Y Tilt"},
|
||||
{BRUSH_MAPPING_ANGLE, "ANGLE", ICON_NONE, "Angle"},
|
||||
{BRUSH_MAPPING_SPEED, "SPEED", ICON_NONE, "Speed"},
|
||||
{BRUSH_MAPPING_RANDOM, "RANDOM", ICON_NONE, "Random"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
@ -658,6 +659,25 @@ void RNA_def_brush_mapping(BlenderRNA *brna)
|
|||
RNA_def_struct_sdna(srna, "BrushMapping");
|
||||
RNA_def_struct_ui_text(srna, "Brush Mapping", "Brush Mapping");
|
||||
|
||||
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, "BrushMapping", "factor");
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Factor", "Mapping factor");
|
||||
|
||||
prop = RNA_def_property(srna, "min", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, "BrushMapping", "min");
|
||||
RNA_def_property_range(prop, -100000, 100000);
|
||||
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.001, 3);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Min", "");
|
||||
|
||||
prop = RNA_def_property(srna, "max", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, "BrushMapping", "max");
|
||||
RNA_def_property_range(prop, -100000, 100000);
|
||||
RNA_def_property_ui_range(prop, -2.0, 2.0, 0.001, 3);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Max", "");
|
||||
|
||||
prop = RNA_def_property(srna, "inherit", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_INHERIT);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
|
@ -690,6 +710,19 @@ void RNA_def_brush_mapping(BlenderRNA *brna)
|
|||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Enabled", "Input Mapping Is Enabled");
|
||||
|
||||
static EnumPropertyItem blend_items[] = {
|
||||
{MA_RAMP_BLEND, "MIX", ICON_NONE, "Mix", ""},
|
||||
{MA_RAMP_MULT, "MULTIPLY", ICON_NONE, "Multiply", ""},
|
||||
{MA_RAMP_DIV, "DIVIDE", ICON_NONE, "Divide", ""},
|
||||
{MA_RAMP_ADD, "ADD", ICON_NONE, "Add", ""},
|
||||
{MA_RAMP_SUB, "SUBTRACT", ICON_NONE, "Subtract", ""},
|
||||
{MA_RAMP_DIFF, "DIFFERENCE", ICON_NONE, "Difference", ""},
|
||||
{0, NULL, 0, NULL, NULL}};
|
||||
prop = RNA_def_property(srna, "blendmode", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, blend_items);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
RNA_def_property_ui_text(prop, "Blend Mode", "Input mapping blend mode");
|
||||
|
||||
prop = RNA_def_property(srna, "ui_expanded", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, "BrushMapping", "flag", BRUSH_MAPPING_UI_EXPANDED);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
|
|
Loading…
Reference in New Issue