38 bool clear_selection_;
46 : use_select_(use_select), clear_selection_(clear_selection)
96 if (
self.clear_selection_) {
151 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
168 const float brush_radius_sq_re =
pow2f(brush_radius_re);
171 for (const int point_i : point_range) {
172 const float3 pos_cu = brush_transform_inv * deformation.positions[point_i];
176 ED_view3d_project_float_v2_m4(ctx_.region, pos_cu, pos_re, projection.values);
178 const float distance_to_brush_sq_re = math::distance_squared(pos_re, brush_pos_re_);
179 if (distance_to_brush_sq_re > brush_radius_sq_re) {
184 const float distance_to_brush_re = std::sqrt(distance_to_brush_sq_re);
186 const float radius_falloff = BKE_brush_curve_strength(
187 brush_, distance_to_brush_re, brush_radius_re);
189 const float weight = brush_strength_ * radius_falloff;
191 selection[point_i] = math::interpolate(selection[point_i], selection_goal_, weight);
204 transforms_.curves_to_world * self_->brush_3d_.position_cu,
207 const float3 brush_cu = transforms_.world_to_curves * brush_wo;
212 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
213 this->paint_point_selection_spherical(selection, brush_transform * brush_cu);
222 const float brush_radius_cu = self_->brush_3d_.radius_cu;
223 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
226 for (const int i : point_range) {
227 const float3 pos_old_cu = deformation.positions[i];
230 const float distance_to_brush_sq_cu = math::distance_squared(pos_old_cu, brush_cu);
231 if (distance_to_brush_sq_cu > brush_radius_sq_cu) {
236 const float distance_to_brush_cu = std::sqrt(distance_to_brush_sq_cu);
239 const float radius_falloff = BKE_brush_curve_strength(
240 brush_, distance_to_brush_cu, brush_radius_cu);
242 const float weight = brush_strength_ * radius_falloff;
244 selection[i] = math::interpolate(selection[i], selection_goal_, weight);
253 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
254 this->paint_curve_selection_projected(brush_transform, selection);
269 const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
270 const float brush_radius_sq_re =
pow2f(brush_radius_re);
273 for (const int curve_i : curves_range) {
274 const float max_weight = threading::parallel_reduce(
275 curves_->points_for_curve(curve_i).drop_back(1),
278 [&](const IndexRange segment_range, const float init) {
279 float max_weight = init;
280 for (const int segment_i : segment_range) {
281 const float3 pos1_cu = brush_transform_inv * deformation.positions[segment_i];
282 const float3 pos2_cu = brush_transform_inv * deformation.positions[segment_i + 1];
286 ED_view3d_project_float_v2_m4(ctx_.region, pos1_cu, pos1_re, projection.values);
287 ED_view3d_project_float_v2_m4(ctx_.region, pos2_cu, pos2_re, projection.values);
289 const float distance_sq_re = dist_squared_to_line_segment_v2(
290 brush_pos_re_, pos1_re, pos2_re);
291 if (distance_sq_re > brush_radius_sq_re) {
294 const float radius_falloff = BKE_brush_curve_strength(
295 brush_, std::sqrt(distance_sq_re), brush_radius_re);
296 const float weight = brush_strength_ * radius_falloff;
297 max_weight = std::max(max_weight, weight);
301 [](float a, float b) { return std::max(a, b); });
302 selection[curve_i] = math::interpolate(selection[curve_i], selection_goal_, max_weight);
315 transforms_.curves_to_world * self_->brush_3d_.position_cu,
318 const float3 brush_cu = transforms_.world_to_curves * brush_wo;
323 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
324 this->paint_curve_selection_spherical(selection, brush_transform * brush_cu);
333 const float brush_radius_cu = self_->brush_3d_.radius_cu;
334 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
337 for (const int curve_i : curves_range) {
338 const float max_weight = threading::parallel_reduce(
339 curves_->points_for_curve(curve_i).drop_back(1),
342 [&](const IndexRange segment_range, const float init) {
343 float max_weight = init;
344 for (const int segment_i : segment_range) {
345 const float3 &pos1_cu = deformation.positions[segment_i];
346 const float3 &pos2_cu = deformation.positions[segment_i + 1];
348 const float distance_sq_cu = dist_squared_to_line_segment_v3(
349 brush_cu, pos1_cu, pos2_cu);
350 if (distance_sq_cu > brush_radius_sq_cu) {
353 const float radius_falloff = BKE_brush_curve_strength(
354 brush_, std::sqrt(distance_sq_cu), brush_radius_cu);
355 const float weight = brush_strength_ * radius_falloff;
356 max_weight = std::max(max_weight, weight);
360 [](float a, float b) { return std::max(a, b); });
361 selection[curve_i] = math::interpolate(selection[curve_i], selection_goal_, max_weight);
374 brush_radius_base_re_);
375 if (brush_3d.has_value()) {
376 self_->brush_3d_ = *brush_3d;
381 void SelectionPaintOperation::on_stroke_extended(
const bContext &
C,
385 executor.execute(*
this,
C, stroke_extension);
397 return std::make_unique<SelectionPaintOperation>(use_select, clear_selection);
float BKE_brush_alpha_get(const struct Scene *scene, const struct Brush *brush)
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush)
struct Scene * CTX_data_scene(const bContext *C)
struct Object * CTX_data_active_object(const bContext *C)
Low-level operations for curves.
struct Brush * BKE_paint_brush(struct Paint *paint)
const struct Brush * BKE_paint_brush_for_read(const struct Paint *p)
MINLINE float pow2f(float x)
void DEG_id_tag_update(struct ID *id, int flag)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
struct CurvesGeometry CurvesGeometry
@ CV_SCULPT_SELECTION_ENABLED
void ED_region_tag_redraw(struct ARegion *region)
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, const struct Object *ob, float r_pmat[4][4])
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
MutableSpan< float > selection_point_float_for_write()
MutableSpan< float > selection_curve_float_for_write()
IndexRange points_range() const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
const Depsgraph * depsgraph
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
SelectionPaintOperation(const bool use_select, const bool clear_selection)
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
std::optional< CurvesBrush3D > sample_curves_3d_brush(const Depsgraph &depsgraph, const ARegion ®ion, const View3D &v3d, const RegionView3D &rv3d, const Object &curves_object, const float2 &brush_pos_re, const float brush_radius_re)
std::unique_ptr< CurvesSculptStrokeOperation > new_selection_paint_operation(const BrushStrokeMode brush_mode, const bContext &C)
Vector< float4x4 > get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
struct ToolSettings * toolsettings
CurvesSculptCommonContext ctx_
void paint_point_selection_spherical_with_symmetry(MutableSpan< float > selection)
CurvesSurfaceTransforms transforms_
void paint_point_selection_spherical(MutableSpan< float > selection, const float3 &brush_cu)
void paint_curve_selection_projected(const float4x4 &brush_transform, MutableSpan< float > selection)
float brush_radius_factor_
SelectionPaintOperation * self_
void paint_point_selection_projected_with_symmetry(MutableSpan< float > selection)
SelectionPaintOperationExecutor(const bContext &C)
void paint_curve_selection_spherical(MutableSpan< float > selection, const float3 &brush_cu)
void paint_point_selection_projected(const float4x4 &brush_transform, MutableSpan< float > selection)
float brush_radius_base_re_
void paint_curve_selection_spherical_with_symmetry(MutableSpan< float > selection)
void paint_curve_selection_projected_with_symmetry(MutableSpan< float > selection)
void execute(SelectionPaintOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
void initialize_spherical_brush_reference_point()
float4x4 inverted() const
void WM_main_add_notifier(unsigned int type, void *reference)