forked from blender/blender
WIP: uv-simple-select #1
@ -522,7 +522,8 @@ class _draw_tool_settings_context_mode:
|
||||
|
||||
if curves_tool == 'COMB':
|
||||
layout.prop(brush, "falloff_shape", expand=True)
|
||||
layout.popover("VIEW3D_PT_tools_brush_falloff")
|
||||
layout.popover("VIEW3D_PT_tools_brush_falloff", text="Brush Falloff")
|
||||
layout.popover("VIEW3D_PT_curves_sculpt_parameter_falloff", text="Curve Falloff")
|
||||
elif curves_tool == 'ADD':
|
||||
layout.prop(brush, "falloff_shape", expand=True)
|
||||
layout.prop(brush.curves_sculpt_settings, "add_amount")
|
||||
@ -7944,6 +7945,28 @@ class VIEW3D_PT_curves_sculpt_add_shape(Panel):
|
||||
col.prop(brush.curves_sculpt_settings, "points_per_curve", text="Points")
|
||||
|
||||
|
||||
class VIEW3D_PT_curves_sculpt_parameter_falloff(Panel):
|
||||
# Only for popover, these are dummy values.
|
||||
bl_space_type = 'VIEW_3D'
|
||||
bl_region_type = 'WINDOW'
|
||||
bl_label = "Curves Sculpt Parameter Falloff"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
settings = UnifiedPaintPanel.paint_settings(context)
|
||||
brush = settings.brush
|
||||
|
||||
layout.template_curve_mapping(brush.curves_sculpt_settings, "curve_parameter_falloff")
|
||||
row = layout.row(align=True)
|
||||
row.operator("brush.sculpt_curves_falloff_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
|
||||
row.operator("brush.sculpt_curves_falloff_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
|
||||
row.operator("brush.sculpt_curves_falloff_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
|
||||
row.operator("brush.sculpt_curves_falloff_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
|
||||
row.operator("brush.sculpt_curves_falloff_preset", icon='LINCURVE', text="").shape = 'LINE'
|
||||
row.operator("brush.sculpt_curves_falloff_preset", icon='NOCURVE', text="").shape = 'MAX'
|
||||
|
||||
|
||||
class VIEW3D_PT_curves_sculpt_grow_shrink_scaling(Panel):
|
||||
# Only for popover, these are dummy values.
|
||||
bl_space_type = 'VIEW_3D'
|
||||
@ -8221,6 +8244,7 @@ classes = (
|
||||
TOPBAR_PT_gpencil_vertexcolor,
|
||||
TOPBAR_PT_annotation_layers,
|
||||
VIEW3D_PT_curves_sculpt_add_shape,
|
||||
VIEW3D_PT_curves_sculpt_parameter_falloff,
|
||||
VIEW3D_PT_curves_sculpt_grow_shrink_scaling,
|
||||
VIEW3D_PT_viewport_debug,
|
||||
)
|
||||
|
@ -100,6 +100,8 @@ static void brush_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, cons
|
||||
if (brush_src->curves_sculpt_settings != nullptr) {
|
||||
brush_dst->curves_sculpt_settings = MEM_cnew<BrushCurvesSculptSettings>(
|
||||
__func__, *(brush_src->curves_sculpt_settings));
|
||||
brush_dst->curves_sculpt_settings->curve_parameter_falloff = BKE_curvemapping_copy(
|
||||
brush_src->curves_sculpt_settings->curve_parameter_falloff);
|
||||
}
|
||||
|
||||
/* enable fake user by default */
|
||||
@ -130,6 +132,7 @@ static void brush_free_data(ID *id)
|
||||
MEM_SAFE_FREE(brush->gpencil_settings);
|
||||
}
|
||||
if (brush->curves_sculpt_settings != nullptr) {
|
||||
BKE_curvemapping_free(brush->curves_sculpt_settings->curve_parameter_falloff);
|
||||
MEM_freeN(brush->curves_sculpt_settings);
|
||||
}
|
||||
|
||||
@ -255,6 +258,7 @@ static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_addres
|
||||
}
|
||||
if (brush->curves_sculpt_settings) {
|
||||
BLO_write_struct(writer, BrushCurvesSculptSettings, brush->curves_sculpt_settings);
|
||||
BKE_curvemapping_blend_write(writer, brush->curves_sculpt_settings->curve_parameter_falloff);
|
||||
}
|
||||
if (brush->gradient) {
|
||||
BLO_write_struct(writer, ColorBand, brush->gradient);
|
||||
@ -337,6 +341,12 @@ static void brush_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
}
|
||||
|
||||
BLO_read_data_address(reader, &brush->curves_sculpt_settings);
|
||||
if (brush->curves_sculpt_settings) {
|
||||
BLO_read_data_address(reader, &brush->curves_sculpt_settings->curve_parameter_falloff);
|
||||
if (brush->curves_sculpt_settings->curve_parameter_falloff) {
|
||||
BKE_curvemapping_blend_read(reader, brush->curves_sculpt_settings->curve_parameter_falloff);
|
||||
}
|
||||
}
|
||||
|
||||
brush->preview = nullptr;
|
||||
brush->icon_imbuf = nullptr;
|
||||
@ -1583,6 +1593,7 @@ void BKE_brush_init_curves_sculpt_settings(Brush *brush)
|
||||
settings->minimum_length = 0.01f;
|
||||
settings->curve_length = 0.3f;
|
||||
settings->density_add_attempts = 100;
|
||||
settings->curve_parameter_falloff = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
|
||||
|
@ -3952,6 +3952,15 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
|
||||
if (brush->ob_mode == OB_MODE_SCULPT_CURVES) {
|
||||
if (brush->curves_sculpt_settings->curve_parameter_falloff == nullptr) {
|
||||
brush->curves_sculpt_settings->curve_parameter_falloff = BKE_curvemapping_add(
|
||||
1, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep this block, even when empty. */
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_bvhutils.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_crazyspace.hh"
|
||||
#include "BKE_curves.hh"
|
||||
@ -69,6 +70,8 @@ class CombOperation : public CurvesSculptStrokeOperation {
|
||||
/** Solver for length and collision constraints. */
|
||||
CurvesConstraintSolver constraint_solver_;
|
||||
|
||||
Array<float> curve_lengths_;
|
||||
|
||||
friend struct CombOperationExecutor;
|
||||
|
||||
public:
|
||||
@ -146,6 +149,17 @@ struct CombOperationExecutor {
|
||||
}
|
||||
self_->constraint_solver_.initialize(
|
||||
*curves_orig_, curve_selection_, curves_id_orig_->flag & CV_SCULPT_COLLISION_ENABLED);
|
||||
|
||||
self_->curve_lengths_.reinitialize(curves_orig_->curves_num());
|
||||
const Span<float> segment_lengths = self_->constraint_solver_.segment_lengths();
|
||||
const OffsetIndices points_by_curve = curves_orig_->points_by_curve();
|
||||
threading::parallel_for(curve_selection_.index_range(), 512, [&](const IndexRange range) {
|
||||
for (const int curve_i : curve_selection_.slice(range)) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
const Span<float> lengths = segment_lengths.slice(points.drop_back(1));
|
||||
self_->curve_lengths_[curve_i] = std::accumulate(lengths.begin(), lengths.end(), 0.0f);
|
||||
}
|
||||
});
|
||||
/* Combing does nothing when there is no mouse movement, so return directly. */
|
||||
return;
|
||||
}
|
||||
@ -204,11 +218,23 @@ struct CombOperationExecutor {
|
||||
const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
|
||||
const float brush_radius_sq_re = pow2f(brush_radius_re);
|
||||
|
||||
CurveMapping &curve_parameter_falloff_mapping =
|
||||
*brush_->curves_sculpt_settings->curve_parameter_falloff;
|
||||
BKE_curvemapping_init(&curve_parameter_falloff_mapping);
|
||||
|
||||
const Span<float> segment_lengths = self_->constraint_solver_.segment_lengths();
|
||||
|
||||
threading::parallel_for(curve_selection_.index_range(), 256, [&](const IndexRange range) {
|
||||
for (const int curve_i : curve_selection_.slice(range)) {
|
||||
bool curve_changed = false;
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
|
||||
const float total_length = self_->curve_lengths_[curve_i];
|
||||
const float total_length_inv = safe_divide(1.0f, total_length);
|
||||
float current_length = 0.0f;
|
||||
for (const int point_i : points.drop_front(1)) {
|
||||
current_length += segment_lengths[point_i - 1];
|
||||
|
||||
const float3 old_pos_cu = deformation.positions[point_i];
|
||||
const float3 old_symm_pos_cu = math::transform_point(brush_transform_inv, old_pos_cu);
|
||||
|
||||
@ -228,8 +254,12 @@ struct CombOperationExecutor {
|
||||
/* A falloff that is based on how far away the point is from the stroke. */
|
||||
const float radius_falloff = BKE_brush_curve_strength(
|
||||
brush_, distance_to_brush_re, brush_radius_re);
|
||||
const float curve_parameter = current_length * total_length_inv;
|
||||
const float curve_falloff = BKE_curvemapping_evaluateF(
|
||||
&curve_parameter_falloff_mapping, 0, curve_parameter);
|
||||
/* Combine the falloff and brush strength. */
|
||||
const float weight = brush_strength_ * radius_falloff * point_factors_[point_i];
|
||||
const float weight = brush_strength_ * curve_falloff * radius_falloff *
|
||||
point_factors_[point_i];
|
||||
|
||||
/* Offset the old point position in screen space and transform it back into 3D space.
|
||||
*/
|
||||
@ -304,15 +334,26 @@ struct CombOperationExecutor {
|
||||
const float brush_radius_sq_cu = pow2f(brush_radius_cu);
|
||||
const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
|
||||
|
||||
CurveMapping &curve_parameter_falloff_mapping =
|
||||
*brush_->curves_sculpt_settings->curve_parameter_falloff;
|
||||
BKE_curvemapping_init(&curve_parameter_falloff_mapping);
|
||||
|
||||
const bke::crazyspace::GeometryDeformation deformation =
|
||||
bke::crazyspace::get_evaluated_curves_deformation(*ctx_.depsgraph, *curves_ob_orig_);
|
||||
const OffsetIndices points_by_curve = curves_orig_->points_by_curve();
|
||||
const Span<float> segment_lengths = self_->constraint_solver_.segment_lengths();
|
||||
|
||||
threading::parallel_for(curve_selection_.index_range(), 256, [&](const IndexRange range) {
|
||||
for (const int curve_i : curve_selection_.slice(range)) {
|
||||
bool curve_changed = false;
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
|
||||
const float total_length = self_->curve_lengths_[curve_i];
|
||||
const float total_length_inv = safe_divide(1.0f, total_length);
|
||||
float current_length = 0.0f;
|
||||
for (const int point_i : points.drop_front(1)) {
|
||||
current_length += segment_lengths[point_i - 1];
|
||||
|
||||
const float3 pos_old_cu = deformation.positions[point_i];
|
||||
|
||||
/* Compute distance to the brush. */
|
||||
@ -328,8 +369,12 @@ struct CombOperationExecutor {
|
||||
/* A falloff that is based on how far away the point is from the stroke. */
|
||||
const float radius_falloff = BKE_brush_curve_strength(
|
||||
brush_, distance_to_brush_cu, brush_radius_cu);
|
||||
const float curve_parameter = current_length * total_length_inv;
|
||||
const float curve_falloff = BKE_curvemapping_evaluateF(
|
||||
&curve_parameter_falloff_mapping, 0, curve_parameter);
|
||||
/* Combine the falloff and brush strength. */
|
||||
const float weight = brush_strength_ * radius_falloff * point_factors_[point_i];
|
||||
const float weight = brush_strength_ * curve_falloff * radius_falloff *
|
||||
point_factors_[point_i];
|
||||
|
||||
const float3 translation_eval_cu = weight * brush_diff_cu;
|
||||
const float3 translation_orig_cu = deformation.translation_from_deformed_to_original(
|
||||
|
@ -163,6 +163,11 @@ struct CurvesConstraintSolver {
|
||||
const IndexMask curve_selection,
|
||||
const Mesh *surface,
|
||||
const CurvesSurfaceTransforms &transforms);
|
||||
|
||||
Span<float> segment_lengths() const
|
||||
{
|
||||
return segment_lengths_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
@ -373,6 +373,7 @@ void paint_sample_color(
|
||||
void paint_stroke_operator_properties(struct wmOperatorType *ot);
|
||||
|
||||
void BRUSH_OT_curve_preset(struct wmOperatorType *ot);
|
||||
void BRUSH_OT_sculpt_curves_falloff_preset(struct wmOperatorType *ot);
|
||||
|
||||
void PAINT_OT_face_select_linked(struct wmOperatorType *ot);
|
||||
void PAINT_OT_face_select_linked_pick(struct wmOperatorType *ot);
|
||||
|
@ -1421,6 +1421,7 @@ void ED_operatortypes_paint(void)
|
||||
WM_operatortype_append(BRUSH_OT_add_gpencil);
|
||||
WM_operatortype_append(BRUSH_OT_scale_size);
|
||||
WM_operatortype_append(BRUSH_OT_curve_preset);
|
||||
WM_operatortype_append(BRUSH_OT_sculpt_curves_falloff_preset);
|
||||
WM_operatortype_append(BRUSH_OT_reset);
|
||||
WM_operatortype_append(BRUSH_OT_stencil_control);
|
||||
WM_operatortype_append(BRUSH_OT_stencil_fit_image_aspect);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_image.h"
|
||||
@ -569,10 +570,7 @@ static bool brush_curve_preset_poll(bContext *C)
|
||||
return br && br->curve;
|
||||
}
|
||||
|
||||
void BRUSH_OT_curve_preset(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
static const EnumPropertyItem prop_shape_items[] = {
|
||||
static const EnumPropertyItem prop_shape_items[] = {
|
||||
{CURVE_PRESET_SHARP, "SHARP", 0, "Sharp", ""},
|
||||
{CURVE_PRESET_SMOOTH, "SMOOTH", 0, "Smooth", ""},
|
||||
{CURVE_PRESET_MAX, "MAX", 0, "Max", ""},
|
||||
@ -580,8 +578,10 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
|
||||
{CURVE_PRESET_ROUND, "ROUND", 0, "Round", ""},
|
||||
{CURVE_PRESET_ROOT, "ROOT", 0, "Root", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
};
|
||||
|
||||
void BRUSH_OT_curve_preset(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Preset";
|
||||
ot->description = "Set brush shape";
|
||||
ot->idname = "BRUSH_OT_curve_preset";
|
||||
@ -589,6 +589,38 @@ void BRUSH_OT_curve_preset(wmOperatorType *ot)
|
||||
ot->exec = brush_curve_preset_exec;
|
||||
ot->poll = brush_curve_preset_poll;
|
||||
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
|
||||
RNA_def_property_translation_context(prop,
|
||||
BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */
|
||||
}
|
||||
|
||||
static bool brush_sculpt_curves_falloff_preset_poll(bContext *C)
|
||||
{
|
||||
Brush *br = BKE_paint_brush(BKE_paint_get_active_from_context(C));
|
||||
return br && br->curves_sculpt_settings && br->curves_sculpt_settings->curve_parameter_falloff;
|
||||
}
|
||||
|
||||
static int brush_sculpt_curves_falloff_preset_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
|
||||
CurveMapping *mapping = brush->curves_sculpt_settings->curve_parameter_falloff;
|
||||
mapping->preset = RNA_enum_get(op->ptr, "shape");
|
||||
CurveMap *map = mapping->cm;
|
||||
BKE_curvemap_reset(map, &mapping->clipr, mapping->preset, CURVEMAP_SLOPE_POSITIVE);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void BRUSH_OT_sculpt_curves_falloff_preset(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Curve Falloff Preset";
|
||||
ot->description = "Set Curve Falloff Preset";
|
||||
ot->idname = "BRUSH_OT_sculpt_curves_falloff_preset";
|
||||
|
||||
ot->exec = brush_sculpt_curves_falloff_preset_exec;
|
||||
ot->poll = brush_sculpt_curves_falloff_preset_poll;
|
||||
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_enum(ot->srna, "shape", prop_shape_items, CURVE_PRESET_SMOOTH, "Mode", "");
|
||||
RNA_def_property_translation_context(prop,
|
||||
BLT_I18NCONTEXT_ID_CURVE_LEGACY); /* Abusing id_curve :/ */
|
||||
|
@ -162,7 +162,8 @@ typedef struct BrushCurvesSculptSettings {
|
||||
int density_add_attempts;
|
||||
/** #eBrushCurvesSculptDensityMode. */
|
||||
uint8_t density_mode;
|
||||
char _pad[7];
|
||||
char _pad[3];
|
||||
struct CurveMapping *curve_parameter_falloff;
|
||||
} BrushCurvesSculptSettings;
|
||||
|
||||
typedef struct Brush {
|
||||
|
@ -2106,6 +2106,12 @@ static void rna_def_curves_sculpt_options(BlenderRNA *brna)
|
||||
RNA_def_property_enum_items(prop, density_mode_items);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Density Mode", "Determines whether the brush adds or removes curves");
|
||||
|
||||
prop = RNA_def_property(srna, "curve_parameter_falloff", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "CurveMapping");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Curve Parameter Falloff",
|
||||
"Falloff that is applied from the tip to the root of each curve");
|
||||
}
|
||||
|
||||
static void rna_def_brush(BlenderRNA *brna)
|
||||
|
Loading…
Reference in New Issue
Block a user