Curves: Add initial transform support

This adds basic support for the transform operators for curves.

Differential Revision: https://developer.blender.org/D17063
This commit is contained in:
Falk David 2023-01-21 20:38:36 +01:00
parent 0b17d171d7
commit 50387964b6
7 changed files with 118 additions and 3 deletions

View File

@ -5332,7 +5332,10 @@ class VIEW3D_MT_edit_curves(Menu):
bl_label = "Curves"
def draw(self, _context):
pass
layout = self.layout
layout.menu("VIEW3D_MT_transform")
layout.separator()
class VIEW3D_MT_object_mode_pie(Menu):

View File

@ -56,8 +56,7 @@ IndexMask retrieve_selected_curves(const Curves &curves_id, Vector<int64_t> &r_i
return retrieve_selected_curves(curves, r_indices);
}
static IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves,
Vector<int64_t> &r_indices)
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, Vector<int64_t> &r_indices)
{
return index_mask_ops::find_indices_from_virtual_array(
curves.points_range(),

View File

@ -94,6 +94,7 @@ IndexMask retrieve_selected_curves(const Curves &curves_id, Vector<int64_t> &r_i
* Find points that are selected (a selection factor greater than zero),
* or points in curves with a selection factor greater than zero).
*/
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, Vector<int64_t> &r_indices);
IndexMask retrieve_selected_points(const Curves &curves_id, Vector<int64_t> &r_indices);
/**

View File

@ -30,6 +30,7 @@ set(SRC
transform_convert_armature.c
transform_convert_cursor.c
transform_convert_curve.c
transform_convert_curves.cc
transform_convert_gpencil.c
transform_convert_graph.c
transform_convert_lattice.c

View File

@ -713,6 +713,7 @@ static void init_proportional_edit(TransInfo *t)
if (!ELEM(t->data_type,
&TransConvertType_Action,
&TransConvertType_Curve,
&TransConvertType_Curves,
&TransConvertType_Graph,
&TransConvertType_GPencil,
&TransConvertType_Lattice,
@ -784,6 +785,7 @@ static void init_TransDataContainers(TransInfo *t,
&TransConvertType_Pose,
&TransConvertType_EditArmature,
&TransConvertType_Curve,
&TransConvertType_Curves,
&TransConvertType_GPencil,
&TransConvertType_Lattice,
&TransConvertType_MBall,
@ -959,6 +961,9 @@ static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj
if (t->obedit_type == OB_ARMATURE) {
return &TransConvertType_EditArmature;
}
if (t->obedit_type == OB_CURVES) {
return &TransConvertType_Curves;
}
return NULL;
}
if (ob && (ob->mode & OB_MODE_POSE)) {

View File

@ -134,6 +134,10 @@ extern TransConvertTypeInfo TransConvertType_Cursor3D;
extern TransConvertTypeInfo TransConvertType_Curve;
/* transform_convert_curves.cc */
extern TransConvertTypeInfo TransConvertType_Curves;
/* transform_convert_graph.c */
extern TransConvertTypeInfo TransConvertType_Graph;

View File

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edtransform
*/
#include "BLI_array.hh"
#include "BLI_index_mask_ops.hh"
#include "BLI_span.hh"
#include "BKE_curves.hh"
#include "ED_curves.h"
#include "MEM_guardedalloc.h"
#include "transform.h"
#include "transform_convert.h"
/* -------------------------------------------------------------------- */
/** \name Curve/Surfaces Transform Creation
* \{ */
namespace blender::ed::transform::curves {
static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
{
MutableSpan<TransDataContainer> trans_data_contrainers(t->data_container, t->data_container_len);
Array<Vector<int64_t>> selected_indices_per_object(t->data_container_len);
Array<IndexMask> selection_per_object(t->data_container_len);
/* Count selected elements per object and create TransData structs. */
for (const int i : trans_data_contrainers.index_range()) {
TransDataContainer &tc = trans_data_contrainers[i];
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
selection_per_object[i] = ed::curves::retrieve_selected_points(curves,
selected_indices_per_object[i]);
tc.data_len = selection_per_object[i].size();
if (tc.data_len > 0) {
tc.data = MEM_cnew_array<TransData>(tc.data_len, __func__);
}
}
/* Populate TransData structs. */
for (const int i : trans_data_contrainers.index_range()) {
TransDataContainer &tc = trans_data_contrainers[i];
if (tc.data_len == 0) {
continue;
}
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
IndexMask selected_indices = selection_per_object[i];
float mtx[3][3], smtx[3][3];
copy_m3_m4(mtx, tc.obedit->object_to_world);
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
MutableSpan<float3> positions = curves.positions_for_write();
threading::parallel_for(selected_indices.index_range(), 1024, [&](const IndexRange range) {
for (const int selection_i : range) {
TransData *td = &tc.data[selection_i];
float *elem = reinterpret_cast<float *>(&positions[selected_indices[selection_i]]);
copy_v3_v3(td->iloc, elem);
copy_v3_v3(td->center, td->iloc);
td->loc = elem;
td->flag = TD_SELECTED;
td->ext = nullptr;
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
}
});
}
}
static void recalcData_curves(TransInfo *t)
{
Span<TransDataContainer> trans_data_contrainers(t->data_container, t->data_container_len);
for (const TransDataContainer &tc : trans_data_contrainers) {
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
curves.calculate_bezier_auto_handles();
curves.tag_positions_changed();
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
}
}
} // namespace blender::ed::transform::curves
/** \} */
TransConvertTypeInfo TransConvertType_Curves = {
/*flags*/ (T_EDIT | T_POINTS),
/*createTransData*/ blender::ed::transform::curves::createTransCurvesVerts,
/*recalcData*/ blender::ed::transform::curves::recalcData_curves,
/*special_aftertrans_update*/ nullptr,
};