Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Dobarro <pablodp606@gmail.com>2020-07-20 01:37:41 +0300
committerPablo Dobarro <pablodp606@gmail.com>2020-07-21 23:43:39 +0300
commit69afdf69702c8f1d4d43f7369a94bb36a4a349f2 (patch)
tree5f66807e13a31774a4a287250c45d8fc91b518e5
parent4aa2a5481cec4edc4694ee1edbde4ed3f3986313 (diff)
Sculpt: Support pen pressure modulation in Paint Brush properties
This allows to use pen pressure modulation in hardness, wet mix, wet persistence, flow and density, as well as inverting the modulation (more pressure, less density...). With this, it is possible to create brushes that mix paint or apply a new color based on the pressure. Reviewed By: sergey, campbellbarton Differential Revision: https://developer.blender.org/D8267
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py38
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c48
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h9
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_color.c17
-rw-r--r--source/blender/makesdna/DNA_brush_types.h16
-rw-r--r--source/blender/makesrna/intern/rna_brush.c78
6 files changed, 189 insertions, 17 deletions
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 004bcaf819b..5044d1be34c 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -544,7 +544,11 @@ def brush_settings(layout, context, brush, popover=False):
# normal_radius_factor
layout.prop(brush, "normal_radius_factor", slider=True)
- layout.prop(brush, "hardness", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(brush, "hardness", slider=True)
+ row.prop(brush, "invert_hardness_pressure", text = "")
+ row.prop(brush, "use_hardness_pressure", text = "")
# auto_smooth_factor and use_inverse_smooth_pressure
if capabilities.has_auto_smooth:
@@ -674,13 +678,31 @@ def brush_settings(layout, context, brush, popover=False):
layout.prop(brush, "use_grab_active_vertex")
if brush.sculpt_tool == 'PAINT':
- col = layout.column()
- col.prop(brush, "flow")
- col.prop(brush, "wet_mix")
- col.prop(brush, "wet_persistence")
- col.prop(brush, "density")
- col.prop(brush, "tip_roundness")
- col.prop(brush, "tip_scale_x")
+ row = layout.row(align=True)
+ row.prop(brush, "flow")
+ row.prop(brush, "invert_flow_pressure", text = "")
+ row.prop(brush, "use_flow_pressure", 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 = "")
+
+ row = layout.row(align=True)
+ row.prop(brush, "wet_persistence")
+ row.prop(brush, "invert_wet_persistence_pressure", text ="")
+ row.prop(brush, "use_wet_persistence_pressure", text= "")
+
+ row = layout.row(align=True)
+ row.prop(brush, "density")
+ row.prop(brush, "invert_density_pressure", text = "")
+ row.prop(brush, "use_density_pressure", text = "")
+
+ row = layout.row()
+ row.prop(brush, "tip_roundness")
+
+ row = layout.row()
+ row.prop(brush, "tip_scale_x")
if brush.sculpt_tool == 'SMEAR':
col = layout.column()
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 02b736c00c2..e679c62fdaa 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -2418,7 +2418,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
/* Hardness. */
float final_len = len;
- const float hardness = br->hardness;
+ const float hardness = cache->paint_brush.hardness;
float p = len / cache->radius;
if (p < hardness) {
final_len = 0.0f;
@@ -6618,6 +6618,50 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
}
}
+static void sculpt_update_cache_paint_variants(StrokeCache *cache, const Brush *brush)
+{
+ cache->paint_brush.hardness = brush->hardness;
+ if (brush->paint_flags & BRUSH_PAINT_HARDNESS_PRESSURE) {
+ cache->paint_brush.hardness *= brush->paint_flags & BRUSH_PAINT_HARDNESS_PRESSURE_INVERT ?
+ 1.0f - cache->pressure :
+ cache->pressure;
+ }
+
+ cache->paint_brush.flow = brush->flow;
+ if (brush->paint_flags & BRUSH_PAINT_FLOW_PRESSURE) {
+ cache->paint_brush.flow *= brush->paint_flags & BRUSH_PAINT_FLOW_PRESSURE_INVERT ?
+ 1.0f - cache->pressure :
+ cache->pressure;
+ }
+
+ cache->paint_brush.wet_mix = brush->wet_mix;
+ if (brush->paint_flags & BRUSH_PAINT_WET_MIX_PRESSURE) {
+ cache->paint_brush.wet_mix *= brush->paint_flags & BRUSH_PAINT_WET_MIX_PRESSURE_INVERT ?
+ 1.0f - cache->pressure :
+ cache->pressure;
+
+ /* This makes wet mix more sensible in higher values, which allows to create brushes that have
+ * a wider pressure range were they only blend colors without applying too much of the brush
+ * color. */
+ cache->paint_brush.wet_mix = 1.0f - pow2f(1.0f - cache->paint_brush.wet_mix);
+ }
+
+ cache->paint_brush.wet_persistence = brush->wet_persistence;
+ if (brush->paint_flags & BRUSH_PAINT_WET_PERSISTENCE_PRESSURE) {
+ cache->paint_brush.wet_persistence = brush->paint_flags &
+ BRUSH_PAINT_WET_PERSISTENCE_PRESSURE_INVERT ?
+ 1.0f - cache->pressure :
+ cache->pressure;
+ }
+
+ cache->paint_brush.density = brush->density;
+ if (brush->paint_flags & BRUSH_PAINT_DENSITY_PRESSURE) {
+ cache->paint_brush.density = brush->paint_flags & BRUSH_PAINT_DENSITY_PRESSURE_INVERT ?
+ 1.0f - cache->pressure :
+ cache->pressure;
+ }
+}
+
/* Initialize the stroke cache variants from operator properties. */
static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, PointerRNA *ptr)
{
@@ -6684,6 +6728,8 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
cache->dyntopo_pixel_radius = ups->initial_pixel_radius;
}
+ sculpt_update_cache_paint_variants(cache, brush);
+
cache->radius_squared = cache->radius * cache->radius;
if (brush->flag & BRUSH_ANCHORED) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 17c7e9e86c0..f834ab7b179 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -827,6 +827,15 @@ typedef struct StrokeCache {
bool original;
float anchored_location[3];
+ /* Paint Brush. */
+ struct {
+ float hardness;
+ float flow;
+ float wet_mix;
+ float wet_persistence;
+ float density;
+ } paint_brush;
+
/* Pose brush */
struct SculptPoseIKChain *pose_ik_chain;
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
index 608ba1b934e..f01a914fdd3 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
@@ -164,7 +164,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
/* Density. */
float noise = 1.0f;
- const float density = brush->density;
+ const float density = ss->cache->paint_brush.density;
if (density < 1.0f) {
const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index);
if (hash_noise > density) {
@@ -178,11 +178,12 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
float wet_mix_color[4];
float buffer_color[4];
- mul_v4_v4fl(paint_color, brush_color, fade * brush->flow);
- mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * brush->flow);
+ mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow);
+ mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow);
/* Interpolate with the wet_mix color for wet paint mixing. */
- blend_color_interpolate_float(paint_color, paint_color, wet_mix_color, brush->wet_mix);
+ blend_color_interpolate_float(
+ paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix);
blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color);
/* Final mix over the original color using brush alpha. */
@@ -305,7 +306,7 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
/* Wet paint color sampling. */
float wet_color[4] = {0.0f};
- if (brush->wet_mix > 0.0f) {
+ if (ss->cache->paint_brush.wet_mix > 0.0f) {
SculptThreadedTaskData task_data = {
.sd = sd,
.ob = ob,
@@ -332,8 +333,10 @@ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
if (ss->cache->first_time) {
copy_v4_v4(ss->cache->wet_mix_prev_color, wet_color);
}
- blend_color_interpolate_float(
- wet_color, wet_color, ss->cache->wet_mix_prev_color, brush->wet_persistence);
+ blend_color_interpolate_float(wet_color,
+ wet_color,
+ ss->cache->wet_mix_prev_color,
+ ss->cache->paint_brush.wet_persistence);
copy_v4_v4(ss->cache->wet_mix_prev_color, wet_color);
CLAMP4(ss->cache->wet_mix_prev_color, 0.0f, 1.0f);
}
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 0ad249ef2cd..76a172d6fda 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -388,6 +388,19 @@ typedef enum eAutomasking_flag {
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS = (1 << 3),
} eAutomasking_flag;
+typedef enum ePaintBrush_flag {
+ BRUSH_PAINT_HARDNESS_PRESSURE = (1 << 0),
+ BRUSH_PAINT_HARDNESS_PRESSURE_INVERT = (1 << 1),
+ BRUSH_PAINT_FLOW_PRESSURE = (1 << 2),
+ BRUSH_PAINT_FLOW_PRESSURE_INVERT = (1 << 3),
+ BRUSH_PAINT_WET_MIX_PRESSURE = (1 << 4),
+ BRUSH_PAINT_WET_MIX_PRESSURE_INVERT = (1 << 5),
+ BRUSH_PAINT_WET_PERSISTENCE_PRESSURE = (1 << 6),
+ BRUSH_PAINT_WET_PERSISTENCE_PRESSURE_INVERT = (1 << 7),
+ BRUSH_PAINT_DENSITY_PRESSURE = (1 << 8),
+ BRUSH_PAINT_DENSITY_PRESSURE_INVERT = (1 << 9),
+} ePaintBrush_flag;
+
typedef struct Brush {
ID id;
@@ -454,6 +467,7 @@ typedef struct Brush {
float wet_persistence;
/** Density */
float density;
+ int paint_flags;
/** Tip Shape */
/* Factor that controls the shape of the brush tip by rounding the corners of a square. */
@@ -480,7 +494,7 @@ typedef struct Brush {
/** Source for fill tool color gradient application. */
char gradient_fill_mode;
- char _pad0[1];
+ char _pad0[5];
/** Projection shape (sphere, circle). */
char falloff_shape;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index b4703ab9aa2..43f31922292 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -2283,6 +2283,84 @@ static void rna_def_brush(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Tip Scale X", "Scale of the brush tip in the X axis");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_hardness_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_HARDNESS_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure for Hardness", "Use pressure to modulate hardness");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "invert_hardness_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_HARDNESS_PRESSURE_INVERT);
+ RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
+ RNA_def_property_ui_text(
+ prop, "Invert Pressure for Hardness", "Invert the modulation of pressure in hardness");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "use_flow_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_FLOW_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure for Flow", "Use pressure to modulate flow");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "invert_flow_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_FLOW_PRESSURE_INVERT);
+ RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
+ RNA_def_property_ui_text(
+ prop, "Invert Pressure for Flow", "Invert the modulation of pressure in flow");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "use_wet_mix_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_WET_MIX_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure for Wet Mix", "Use pressure to modulate wet mix");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "invert_wet_mix_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_WET_MIX_PRESSURE_INVERT);
+ RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
+ RNA_def_property_ui_text(
+ prop, "Invert Pressure for Wet Mix", "Invert the modulation of pressure in wet mix");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "use_wet_persistence_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_WET_PERSISTENCE_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(
+ prop, "Use Pressure for Wet Persistence", "Use pressure to modulate wet persistence");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "invert_wet_persistence_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "paint_flags", BRUSH_PAINT_WET_PERSISTENCE_PRESSURE_INVERT);
+ RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
+ RNA_def_property_ui_text(prop,
+ "Invert Pressure for Wet Persistence",
+ "Invert the modulation of pressure in wet persistence");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "use_density_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_DENSITY_PRESSURE);
+ RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
+ RNA_def_property_ui_text(prop, "Use Pressure for Density", "Use pressure to modulate density");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
+ prop = RNA_def_property(srna, "invert_density_pressure", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "paint_flags", BRUSH_PAINT_DENSITY_PRESSURE_INVERT);
+ RNA_def_property_ui_icon(prop, ICON_ARROW_LEFTRIGHT, 0);
+ RNA_def_property_ui_text(
+ prop, "Invert Pressure for Density", "Invert the modulation of pressure in density");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "dash_ratio", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "dash_ratio");
RNA_def_property_range(prop, 0.0f, 1.0f);