Sculpt: Add per-brush input samples
This pull request adds the ability for users to specify input samples on a per brush basis. The existing field in the main `Paint` struct forces all brushes of a particular tool type to use the same value. A new field was added to the `Brush` struct to allow for this value to be specified there instead, and a corresponding unified value in `UnifiedPaintSettings` has been created to allow users to use the same value across all brushes. Addresses #108109 Pull Request: https://projects.blender.org/blender/blender/pulls/117080
This commit is contained in:
parent
dd7362d6e2
commit
a2b3fe5e01
|
@ -362,7 +362,14 @@ class StrokePanel(BrushPanel):
|
|||
col.row().prop(brush, "jitter_unit", expand=True)
|
||||
|
||||
col.separator()
|
||||
col.prop(settings, "input_samples")
|
||||
UnifiedPaintPanel.prop_unified(
|
||||
layout,
|
||||
context,
|
||||
brush,
|
||||
"input_samples",
|
||||
unified_name="use_unified_input_samples",
|
||||
slider=True,
|
||||
)
|
||||
|
||||
|
||||
class SmoothStrokePanel(BrushPanel):
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 16
|
||||
#define BLENDER_FILE_SUBVERSION 17
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -152,6 +152,9 @@ void BKE_brush_alpha_set(Scene *scene, Brush *brush, float alpha);
|
|||
float BKE_brush_weight_get(const Scene *scene, const Brush *brush);
|
||||
void BKE_brush_weight_set(const Scene *scene, Brush *brush, float value);
|
||||
|
||||
int BKE_brush_input_samples_get(const Scene *scene, const Brush *brush);
|
||||
void BKE_brush_input_samples_set(const Scene *scene, Brush *brush, int value);
|
||||
|
||||
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush);
|
||||
bool BKE_brush_use_alpha_pressure(const Brush *brush);
|
||||
bool BKE_brush_use_size_pressure(const Brush *brush);
|
||||
|
|
|
@ -2451,6 +2451,25 @@ void BKE_brush_weight_set(const Scene *scene, Brush *brush, float value)
|
|||
}
|
||||
}
|
||||
|
||||
int BKE_brush_input_samples_get(const Scene *scene, const Brush *brush)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
||||
return (ups->flag & UNIFIED_PAINT_INPUT_SAMPLES) ? ups->input_samples : brush->input_samples;
|
||||
}
|
||||
|
||||
void BKE_brush_input_samples_set(const Scene *scene, Brush *brush, int value)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
||||
if (ups->flag & UNIFIED_PAINT_INPUT_SAMPLES) {
|
||||
ups->input_samples = value;
|
||||
}
|
||||
else {
|
||||
brush->input_samples = value;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_brush_scale_unprojected_radius(float *unprojected_radius,
|
||||
int new_brush_size,
|
||||
int old_brush_size)
|
||||
|
|
|
@ -1248,10 +1248,6 @@ void BKE_paint_blend_write(BlendWriter *writer, Paint *p)
|
|||
|
||||
void BKE_paint_blend_read_data(BlendDataReader *reader, const Scene *scene, Paint *p)
|
||||
{
|
||||
if (p->num_input_samples < 1) {
|
||||
p->num_input_samples = 1;
|
||||
}
|
||||
|
||||
BLO_read_data_address(reader, &p->cavity_curve);
|
||||
if (p->cavity_curve) {
|
||||
BKE_curvemapping_blend_read(reader, p->cavity_curve);
|
||||
|
|
|
@ -2789,6 +2789,55 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 17)) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
int input_sample_values[10];
|
||||
|
||||
input_sample_values[0] = ts->imapaint.paint.num_input_samples;
|
||||
input_sample_values[1] = ts->sculpt != nullptr ? ts->sculpt->paint.num_input_samples : 1;
|
||||
input_sample_values[2] = ts->curves_sculpt != nullptr ?
|
||||
ts->curves_sculpt->paint.num_input_samples :
|
||||
1;
|
||||
input_sample_values[3] = ts->uvsculpt != nullptr ? ts->uvsculpt->paint.num_input_samples : 1;
|
||||
|
||||
input_sample_values[4] = ts->gp_paint != nullptr ? ts->gp_paint->paint.num_input_samples : 1;
|
||||
input_sample_values[5] = ts->gp_vertexpaint != nullptr ?
|
||||
ts->gp_vertexpaint->paint.num_input_samples :
|
||||
1;
|
||||
input_sample_values[6] = ts->gp_sculptpaint != nullptr ?
|
||||
ts->gp_sculptpaint->paint.num_input_samples :
|
||||
1;
|
||||
input_sample_values[7] = ts->gp_weightpaint != nullptr ?
|
||||
ts->gp_weightpaint->paint.num_input_samples :
|
||||
1;
|
||||
|
||||
input_sample_values[8] = ts->vpaint != nullptr ? ts->vpaint->paint.num_input_samples : 1;
|
||||
input_sample_values[9] = ts->wpaint != nullptr ? ts->wpaint->paint.num_input_samples : 1;
|
||||
|
||||
int unified_value = 1;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (input_sample_values[i] != 1) {
|
||||
if (unified_value == 1) {
|
||||
unified_value = input_sample_values[i];
|
||||
}
|
||||
else {
|
||||
/* In the case of a user having multiple tools with different num_input_value values
|
||||
* set we cannot support this in the single UnifiedPaintSettings value, so fallback
|
||||
* to 1 instead of deciding that one value is more canonical than the other.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ts->unified_paint_settings.input_samples = unified_value;
|
||||
}
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
brush->input_samples = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
|
||||
|
|
|
@ -387,6 +387,11 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
|
|||
if (ts->sculpt) {
|
||||
ts->sculpt->automasking_boundary_edges_propagation_steps = 1;
|
||||
}
|
||||
|
||||
/* Ensure input_samples has a correct default value of 1. */
|
||||
if (ts->unified_paint_settings.input_samples == 0) {
|
||||
ts->unified_paint_settings.input_samples = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
||||
|
@ -679,6 +684,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
|
|||
|
||||
/* Enable anti-aliasing by default. */
|
||||
brush->sampling_flag |= BRUSH_PAINT_ANTIALIASING;
|
||||
|
||||
/* By default, each brush should use a single input sample. */
|
||||
brush->input_samples = 1;
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -1158,10 +1158,10 @@ wmKeyMap *paint_stroke_modal_keymap(wmKeyConfig *keyconf)
|
|||
}
|
||||
|
||||
static void paint_stroke_add_sample(
|
||||
const Paint *paint, PaintStroke *stroke, float x, float y, float pressure)
|
||||
PaintStroke *stroke, int input_samples, float x, float y, float pressure)
|
||||
{
|
||||
PaintSample *sample = &stroke->samples[stroke->cur_sample];
|
||||
int max_samples = std::clamp(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
|
||||
int max_samples = std::clamp(input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
|
||||
|
||||
sample->mouse[0] = x;
|
||||
sample->mouse[1] = y;
|
||||
|
@ -1431,6 +1431,7 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
|
|||
|
||||
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintStroke **stroke_p)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Paint *p = BKE_paint_get_active_from_context(C);
|
||||
PaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
PaintStroke *stroke = *stroke_p;
|
||||
|
@ -1460,7 +1461,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
|
|||
stroke->last_tablet_event_pressure = pressure;
|
||||
}
|
||||
|
||||
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
|
||||
int input_samples = BKE_brush_input_samples_get(scene, br);
|
||||
paint_stroke_add_sample(stroke, input_samples, event->mval[0], event->mval[1], pressure);
|
||||
paint_stroke_sample_average(stroke, &sample_average);
|
||||
|
||||
/* Tilt. */
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
\
|
||||
.jitter = 0.0f, \
|
||||
\
|
||||
.input_samples = 1, \
|
||||
/* Dash */ \
|
||||
.dash_ratio = 1.0f, \
|
||||
.dash_samples = 20, \
|
||||
|
|
|
@ -204,6 +204,9 @@ typedef struct Brush {
|
|||
int flag2;
|
||||
int sampling_flag;
|
||||
|
||||
/** Number of samples used to smooth the stroke. */
|
||||
int input_samples;
|
||||
|
||||
/** Pressure influence for mask. */
|
||||
int mask_pressure;
|
||||
/** Jitter the position of the brush. */
|
||||
|
@ -260,7 +263,7 @@ typedef struct Brush {
|
|||
/** Source for fill tool color gradient application. */
|
||||
char gradient_fill_mode;
|
||||
|
||||
char _pad0[5];
|
||||
char _pad0;
|
||||
|
||||
/** Projection shape (sphere, circle). */
|
||||
char falloff_shape;
|
||||
|
|
|
@ -308,6 +308,7 @@
|
|||
#define _DNA_DEFAULTS_UnifiedPaintSettings \
|
||||
{ \
|
||||
.size = 50, \
|
||||
.input_samples = 1, \
|
||||
.unprojected_radius = 0.29, \
|
||||
.alpha = 0.5f, \
|
||||
.weight = 0.5f, \
|
||||
|
|
|
@ -967,8 +967,12 @@ typedef struct Paint {
|
|||
/** Enum #ePaintFlags. */
|
||||
int flags;
|
||||
|
||||
/** Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES inputs to smooth the stroke. */
|
||||
int num_input_samples;
|
||||
/**
|
||||
* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES inputs to smooth the stroke.
|
||||
* This value is now DEPRECATED, please refer to the Brush and UnifiedPaintSetting values
|
||||
* instead.
|
||||
*/
|
||||
int num_input_samples DNA_DEPRECATED;
|
||||
|
||||
/** Flags used for symmetry. */
|
||||
int symmetry_flags;
|
||||
|
@ -1338,8 +1342,12 @@ typedef struct UnifiedPaintSettings {
|
|||
/** Unified brush secondary color. */
|
||||
float secondary_rgb[3];
|
||||
|
||||
/** Unified brush stroke input samples. */
|
||||
int input_samples;
|
||||
|
||||
/** User preferences for sculpt and paint. */
|
||||
int flag;
|
||||
char _pad[4];
|
||||
|
||||
/* Rake rotation. */
|
||||
|
||||
|
@ -1411,6 +1419,7 @@ typedef enum {
|
|||
UNIFIED_PAINT_ALPHA = (1 << 1),
|
||||
UNIFIED_PAINT_WEIGHT = (1 << 5),
|
||||
UNIFIED_PAINT_COLOR = (1 << 6),
|
||||
UNIFIED_PAINT_INPUT_SAMPLES = (1 << 7),
|
||||
|
||||
/** Only used if unified size is enabled, mirrors the brush flag #BRUSH_LOCK_SIZE. */
|
||||
UNIFIED_PAINT_BRUSH_LOCK_SIZE = (1 << 2),
|
||||
|
|
|
@ -2769,6 +2769,16 @@ static void rna_def_brush(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Unprojected Radius", "Radius of brush in Blender units");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_size_update");
|
||||
|
||||
prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "input_samples");
|
||||
RNA_def_property_range(prop, 1, PAINT_MAX_INPUT_SAMPLES);
|
||||
RNA_def_property_ui_range(prop, 1, PAINT_MAX_INPUT_SAMPLES, 1, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Input Samples",
|
||||
"Number of input samples to average together to smooth the brush stroke");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "jitter", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "jitter");
|
||||
RNA_def_property_range(prop, 0.0f, 1000.0f);
|
||||
|
|
|
@ -4182,6 +4182,13 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(
|
||||
prop, "Use Unified Color", "Instead of per-brush color, the color is shared across brushes");
|
||||
|
||||
prop = RNA_def_property(srna, "use_unified_input_samples", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", UNIFIED_PAINT_INPUT_SAMPLES);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Use Unified Input Samples",
|
||||
"Instead of per-brush input samples, the value is shared across brushes");
|
||||
|
||||
/* unified paint settings that override the equivalent settings
|
||||
* from the active brush */
|
||||
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
|
||||
|
@ -4232,6 +4239,17 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(prop, "Secondary Color", "");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "input_samples");
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_range(prop, 1, PAINT_MAX_INPUT_SAMPLES);
|
||||
RNA_def_property_ui_range(prop, 1, PAINT_MAX_INPUT_SAMPLES, 1, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Input Samples",
|
||||
"Number of input samples to average together to smooth the brush stroke");
|
||||
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_locked_size", PROP_ENUM, PROP_NONE); /* as an enum */
|
||||
RNA_def_property_enum_bitflag_sdna(prop, nullptr, "flag");
|
||||
RNA_def_property_enum_items(prop, brush_size_unit_items);
|
||||
|
|
|
@ -674,13 +674,6 @@ static void rna_def_paint(BlenderRNA *brna)
|
|||
"Update the geometry when it enters the view, providing faster view navigation");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "input_samples", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "num_input_samples");
|
||||
RNA_def_property_ui_range(prop, 1, PAINT_MAX_INPUT_SAMPLES, 1, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Input Samples", "Average multiple input samples together to smooth the brush stroke");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "use_symmetry_x", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "symmetry_flags", PAINT_SYMM_X);
|
||||
RNA_def_property_ui_text(prop, "Symmetry X", "Mirror brush across the X axis");
|
||||
|
|
Loading…
Reference in New Issue