diff --git a/source/blender/editors/transform/transform_convert_curves.cc b/source/blender/editors/transform/transform_convert_curves.cc index 0988c796009..efeb1d8ed3b 100644 --- a/source/blender/editors/transform/transform_convert_curves.cc +++ b/source/blender/editors/transform/transform_convert_curves.cc @@ -466,11 +466,13 @@ void curve_populate_trans_data_structs( const View3D *v3d = static_cast(t.view); const bool hide_handles = (v3d != nullptr) ? (v3d->overlay.handle_display == CURVE_HANDLE_NONE) : false; + const bool use_individual_origin = (t.around == V3D_AROUND_LOCAL_ORIGINS); const Span point_positions = curves.positions(); const VArray point_selection = *curves.attributes().lookup_or_default( ".selection", bke::AttrDomain::Point, true); - std::array, 3> positions_per_selection_attr; + const VArray curve_types = curves.curve_types(); + std::array, 3> positions_per_selection_attr; for (const int selection_i : points_to_transform_per_attr.index_range()) { positions_per_selection_attr[selection_i] = ed::transform::curves::append_positions_to_custom_data( @@ -495,26 +497,58 @@ void curve_populate_trans_data_structs( const float3x3 mtx_base = transform.view<3, 3>(); const float3x3 smtx_base = math::pseudo_invert(mtx_base); + const OffsetIndices points_by_curve = curves.points_by_curve(); + Array mean_center_point_per_curve(curves.curves_num()); + if (use_individual_origin) { + affected_curves.foreach_index(GrainSize(512), [&](const int64_t curve_i) { + const IndexRange points = points_by_curve[curve_i]; + IndexMaskMemory memory; + const IndexMask selection = + IndexMask::from_bools(point_selection, memory).slice_content(points); + if (selection.is_empty()) { + return; + } + float3 center(0.0f); + selection.foreach_index([&](const int64_t point_i) { center += point_positions[point_i]; }); + center /= selection.size(); + mean_center_point_per_curve[curve_i] = center; + }); + } + + const Array point_to_curve_map = curves.point_to_curve_map(); for (const int selection_i : position_offsets_in_td.index_range()) { if (position_offsets_in_td[selection_i].is_empty()) { continue; } MutableSpan tc_data = all_tc_data.slice(position_offsets_in_td[selection_i]); MutableSpan positions = positions_per_selection_attr[selection_i]; - IndexMask points_to_transform = points_to_transform_per_attr[selection_i]; - VArray selection = selection_attrs[selection_i]; + const IndexMask points_to_transform = points_to_transform_per_attr[selection_i]; + const VArray selection = selection_attrs[selection_i]; points_to_transform.foreach_index( GrainSize(1024), [&](const int64_t domain_i, const int64_t transform_i) { + const int curve_i = point_to_curve_map[domain_i]; + TransData &td = tc_data[transform_i]; float3 *elem = &positions[transform_i]; + float3 center; + const bool use_local_center = hide_handles || use_individual_origin || + point_selection[domain_i]; + const bool use_mean_center = use_individual_origin && + !(curve_types[curve_i] == CURVE_TYPE_BEZIER); + if (use_mean_center) { + center = mean_center_point_per_curve[curve_i]; + } + else if (use_local_center) { + center = point_positions[domain_i]; + } + else { + center = td.iloc; + } + copy_v3_v3(td.iloc, *elem); - copy_v3_v3(td.center, - hide_handles || (t.around == V3D_AROUND_LOCAL_ORIGINS) || - point_selection[domain_i] ? - point_positions[domain_i] : - td.iloc); + copy_v3_v3(td.center, center); td.loc = *elem; td.flag = 0; @@ -544,8 +578,6 @@ void curve_populate_trans_data_structs( }); } if (use_connected_only) { - const VArray curve_types = curves.curve_types(); - const OffsetIndices points_by_curve = curves.points_by_curve(); Array bezier_offsets_in_td(curves.curves_num() + 1, 0); offset_indices::copy_group_sizes(points_by_curve, bezier_curves, bezier_offsets_in_td); offset_indices::accumulate_counts_to_offsets(bezier_offsets_in_td); diff --git a/source/blender/editors/transform/transform_convert_grease_pencil.cc b/source/blender/editors/transform/transform_convert_grease_pencil.cc index c0f0fcc2af7..270ac207e2b 100644 --- a/source/blender/editors/transform/transform_convert_grease_pencil.cc +++ b/source/blender/editors/transform/transform_convert_grease_pencil.cc @@ -34,6 +34,7 @@ static void createTransGreasePencilVerts(bContext *C, TransInfo *t) MutableSpan trans_data_contrainers(t->data_container, t->data_container_len); const bool use_proportional_edit = (t->flag & T_PROP_EDIT_ALL) != 0; const bool use_connected_only = (t->flag & T_PROP_CONNECTED) != 0; + const bool use_individual_origins = (t->around == V3D_AROUND_LOCAL_ORIGINS); ToolSettings *ts = scene->toolsettings; const bool is_scale_thickness = ((t->mode == TFM_CURVE_SHRINKFATTEN) || (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SCALE_THICKNESS)); @@ -205,7 +206,7 @@ static void createTransGreasePencilVerts(bContext *C, TransInfo *t) value_attribute = opacities; } - const IndexMask affected_strokes = use_proportional_edit ? + const IndexMask affected_strokes = use_proportional_edit || use_individual_origins ? ed::greasepencil::retrieve_editable_strokes( *object, info.drawing, info.layer_index, memory) : IndexMask();