From a265b591bede2a6cf9cda189bee641cbbe94a5a9 Mon Sep 17 00:00:00 2001 From: Falk David Date: Tue, 3 Dec 2024 16:23:31 +0100 Subject: [PATCH] Python: Add API function to reorder curves The order of curves in a Grease Pencil drawing defines the order in wich they are rendered, so it's important to be able to change the order. Currently, there is not easy way to do this from python. This adds a new `reorder_curves` and `reorder_strokes` function to reorder the curves in the curves geometry. The function takes in an array of indices that are the new indices for the curves (e.g. an index map). `reorder_curves(new_indices=[...])` Pull Request: https://projects.blender.org/blender/blender/pulls/130331 --- .../editors/curves/intern/curves_edit.cc | 7 +++ source/blender/editors/include/ED_curves.hh | 6 ++ .../blender/makesrna/intern/rna_curves_api.cc | 63 +++++++++++++++++++ .../makesrna/intern/rna_curves_utils.hh | 5 ++ .../makesrna/intern/rna_grease_pencil_api.cc | 39 ++++++++++++ 5 files changed, 120 insertions(+) diff --git a/source/blender/editors/curves/intern/curves_edit.cc b/source/blender/editors/curves/intern/curves_edit.cc index b7fc59004eb..8ff00a5f20b 100644 --- a/source/blender/editors/curves/intern/curves_edit.cc +++ b/source/blender/editors/curves/intern/curves_edit.cc @@ -12,6 +12,8 @@ #include "BKE_curves.hh" #include "BKE_curves_utils.hh" +#include "GEO_reorder.hh" + #include "ED_curves.hh" namespace blender::ed::curves { @@ -319,4 +321,9 @@ void resize_curves(bke::CurvesGeometry &curves, curves.tag_topology_changed(); } +void reorder_curves(bke::CurvesGeometry &curves, const Span old_by_new_indices_map) +{ + curves = geometry::reorder_curves_geometry(curves, old_by_new_indices_map, {}); +} + } // namespace blender::ed::curves diff --git a/source/blender/editors/include/ED_curves.hh b/source/blender/editors/include/ED_curves.hh index 36d5e4dbd56..d09a498c855 100644 --- a/source/blender/editors/include/ED_curves.hh +++ b/source/blender/editors/include/ED_curves.hh @@ -453,6 +453,12 @@ void add_curves(bke::CurvesGeometry &curves, Span new_sizes); void resize_curves(bke::CurvesGeometry &curves, const IndexMask &curves_to_resize, Span new_sizes); +/** + * Reorders the curves in \a curves. + * \param old_by_new_indices_map: An index mapping where each value is the target index for the + * reorder curves. + */ +void reorder_curves(bke::CurvesGeometry &curves, Span old_by_new_indices_map); /** \} */ diff --git a/source/blender/makesrna/intern/rna_curves_api.cc b/source/blender/makesrna/intern/rna_curves_api.cc index 989d24cf4ae..c01d6ca3a4f 100644 --- a/source/blender/makesrna/intern/rna_curves_api.cc +++ b/source/blender/makesrna/intern/rna_curves_api.cc @@ -21,6 +21,7 @@ # include "BKE_report.hh" # include "BLI_index_mask.hh" +# include "BLI_set.hh" # include "ED_curves.hh" @@ -122,6 +123,33 @@ bool rna_CurvesGeometry_resize_curves(blender::bke::CurvesGeometry &curves, return true; } +bool rna_CurvesGeometry_reorder_curves(blender::bke::CurvesGeometry &curves, + ReportList *reports, + const int *reorder_indices_ptr, + const int reorder_indices_num) +{ + using namespace blender; + const Span new_to_old_indices_map(reorder_indices_ptr, reorder_indices_num); + if (curves.curves_num() != reorder_indices_num) { + BKE_report( + reports, RPT_ERROR, "Length of reorder indices must be the same as the number of curves"); + return false; + } + if (std::any_of(new_to_old_indices_map.begin(), + new_to_old_indices_map.end(), + [&](const int index) { return !curves.curves_range().contains(index); })) + { + BKE_report(reports, RPT_ERROR, "Reorder indices must be valid"); + return false; + } + if (Set(new_to_old_indices_map).size() != reorder_indices_num) { + BKE_report(reports, RPT_ERROR, "Reorder indices must not have duplicates"); + return false; + } + ed::curves::reorder_curves(curves, new_to_old_indices_map); + return true; +} + bool rna_CurvesGeometry_set_types(blender::bke::CurvesGeometry &curves, ReportList *reports, const int type, @@ -198,6 +226,26 @@ static void rna_Curves_resize_curves(Curves *curves_id, } } +static void rna_Curves_reorder_curves(Curves *curves_id, + ReportList *reports, + const int *reorder_indices_ptr, + const int reorder_indices_num) +{ + using namespace blender; + bke::CurvesGeometry &curves = curves_id->geometry.wrap(); + if (!rna_CurvesGeometry_reorder_curves( + curves, reports, reorder_indices_ptr, reorder_indices_num)) + { + return; + } + + /* Avoid updates for importers creating curves. */ + if (curves_id->id.us > 0) { + DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_GEOM | ND_DATA, curves_id); + } +} + static void rna_Curves_set_types(Curves *curves_id, ReportList *reports, const int type, @@ -298,6 +346,21 @@ void RNA_api_curves(StructRNA *srna) 10000); RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0)); + func = RNA_def_function(srna, "reorder_curves", "rna_Curves_reorder_curves"); + RNA_def_function_ui_description(func, "Reorder the curves by the new indices."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_int_array(func, + "new_indices", + 1, + nullptr, + 0, + INT_MAX, + "New indices", + "The new index for each of the curves", + 0, + 10000); + RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); + func = RNA_def_function(srna, "set_types", "rna_Curves_set_types"); RNA_def_function_ui_description(func, "Set the curve type. If indices are provided, set only the " diff --git a/source/blender/makesrna/intern/rna_curves_utils.hh b/source/blender/makesrna/intern/rna_curves_utils.hh index abe317d4623..bdb2e3d01c0 100644 --- a/source/blender/makesrna/intern/rna_curves_utils.hh +++ b/source/blender/makesrna/intern/rna_curves_utils.hh @@ -35,6 +35,11 @@ bool rna_CurvesGeometry_resize_curves(blender::bke::CurvesGeometry &curves, const int *indices_ptr, int indices_num); +bool rna_CurvesGeometry_reorder_curves(blender::bke::CurvesGeometry &curves, + ReportList *reports, + const int *reorder_indices_ptr, + int reorder_indices_num); + bool rna_CurvesGeometry_set_types(blender::bke::CurvesGeometry &curves, ReportList *reports, int type, diff --git a/source/blender/makesrna/intern/rna_grease_pencil_api.cc b/source/blender/makesrna/intern/rna_grease_pencil_api.cc index df61477bd15..9dc3be60b4e 100644 --- a/source/blender/makesrna/intern/rna_grease_pencil_api.cc +++ b/source/blender/makesrna/intern/rna_grease_pencil_api.cc @@ -108,6 +108,30 @@ static void rna_GreasePencilDrawing_resize_curves(ID *grease_pencil_id, } } +static void rna_GreasePencilDrawing_reorder_curves(ID *grease_pencil_id, + GreasePencilDrawing *drawing_ptr, + ReportList *reports, + const int *reorder_indices_ptr, + const int reorder_indices_num) +{ + using namespace blender; + bke::greasepencil::Drawing &drawing = drawing_ptr->wrap(); + bke::CurvesGeometry &curves = drawing.strokes_for_write(); + if (!rna_CurvesGeometry_reorder_curves( + curves, reports, reorder_indices_ptr, reorder_indices_num)) + { + return; + } + + drawing.tag_topology_changed(); + + /* Avoid updates for importers. */ + if (grease_pencil_id->us > 0) { + DEG_id_tag_update(grease_pencil_id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_GEOM | ND_DATA, grease_pencil_id); + } +} + static void rna_GreasePencilDrawing_set_types(ID *grease_pencil_id, GreasePencilDrawing *drawing_ptr, ReportList *reports, @@ -517,6 +541,21 @@ void RNA_api_grease_pencil_drawing(StructRNA *srna) 10000); RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0)); + func = RNA_def_function(srna, "reorder_strokes", "rna_GreasePencilDrawing_reorder_curves"); + RNA_def_function_ui_description(func, "Reorder the strokes by the new indices."); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + parm = RNA_def_int_array(func, + "new_indices", + 1, + nullptr, + 0, + INT_MAX, + "New indices", + "The new index for each of the strokes", + 0, + 10000); + RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); + func = RNA_def_function(srna, "set_types", "rna_GreasePencilDrawing_set_types"); RNA_def_function_ui_description(func, "Set the curve type. If indices are provided, set only the "