From 5db88ff2e3457763ceb6090378a5ccc8bb45ab48 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Mon, 4 Nov 2024 18:25:18 +0100 Subject: [PATCH] Curves: Add method to set curve types to RNA Currently writing to the curve type attribute directly from Python doesn't work because it doesn't tag the curve topology changed. This is a limitation with the Python attribute API that needs to be solved generally. In the meantime, this commit adds a `set_types` RNA function. This will have better performance than writing to the attribute directly anyway. This is an alternative to #128410 that avoids tying the type to the addition of curves. Pull Request: https://projects.blender.org/blender/blender/pulls/129224 --- .../blender/makesrna/intern/rna_curves_api.cc | 163 +++++++++++------- .../makesrna/intern/rna_curves_utils.hh | 6 + .../makesrna/intern/rna_grease_pencil_api.cc | 39 +++++ 3 files changed, 149 insertions(+), 59 deletions(-) diff --git a/source/blender/makesrna/intern/rna_curves_api.cc b/source/blender/makesrna/intern/rna_curves_api.cc index 1855f24b129..e7e8d08747a 100644 --- a/source/blender/makesrna/intern/rna_curves_api.cc +++ b/source/blender/makesrna/intern/rna_curves_api.cc @@ -6,8 +6,12 @@ * \ingroup RNA */ +#include "DNA_curves_types.h" + #include "RNA_define.hh" +#include "RNA_enum_types.hh" + #include "rna_internal.hh" /* own include */ #ifdef RNA_RUNTIME @@ -23,6 +27,11 @@ /* Common `CurvesGeometry` API functions. */ +using blender::IndexMask; +using blender::IndexMaskMemory; +using blender::IndexRange; +using blender::Span; + bool rna_CurvesGeometry_add_curves(blender::bke::CurvesGeometry &curves, ReportList *reports, const int *sizes_ptr, @@ -39,40 +48,49 @@ bool rna_CurvesGeometry_add_curves(blender::bke::CurvesGeometry &curves, return true; } +static std::optional rna_indices_to_mask(const IndexRange universe, + const int *indices_ptr, + const int indices_num, + ReportList &reports, + IndexMaskMemory &memory) +{ + if (!indices_ptr) { + return IndexMask(universe); + } + const Span indices(indices_ptr, indices_num); + if (std::any_of(indices.begin(), indices.end(), [&](const int index) { + return !universe.contains(index); + })) + { + BKE_report(&reports, RPT_ERROR, "Indices must be in range"); + return std::nullopt; + } + if (!std::is_sorted(indices.begin(), indices.end())) { + BKE_report(&reports, RPT_ERROR, "Indices must be sorted in ascending order"); + return std::nullopt; + } + if (std::adjacent_find(indices.begin(), indices.end(), std::greater_equal()) != + indices.end()) + { + BKE_report(&reports, RPT_ERROR, "Indices can't have duplicates"); + return std::nullopt; + } + return IndexMask::from_indices(indices, memory); +} + bool rna_CurvesGeometry_remove_curves(blender::bke::CurvesGeometry &curves, ReportList *reports, const int *indices_ptr, const int indices_num) { using namespace blender; - if (indices_ptr != nullptr) { - const Span indices(indices_ptr, indices_num); - if (std::any_of(indices.begin(), indices.end(), [&](const int index) { - return !curves.curves_range().contains(index); - })) - { - BKE_report(reports, RPT_ERROR, "Indices must be in range"); - return false; - } - if (!std::is_sorted(indices.begin(), indices.end())) { - BKE_report(reports, RPT_ERROR, "Indices must be sorted in ascending order"); - return false; - } - if (std::adjacent_find(indices.begin(), indices.end(), std::greater_equal()) != - indices.end()) - { - BKE_report(reports, RPT_ERROR, "Indices can't have duplicates"); - return false; - } - /* Remove the curves by their indices. */ - IndexMaskMemory memory; - IndexMask curves_to_delete = IndexMask::from_indices(indices, memory); - curves.remove_curves(curves_to_delete, {}); - } - else { - /* Clear the CurvesGeometry. */ - curves = {}; + IndexMaskMemory memory; + const std::optional curves_to_delete = rna_indices_to_mask( + curves.curves_range(), indices_ptr, indices_num, *reports, memory); + if (!curves_to_delete) { + return false; } + curves.remove_curves(*curves_to_delete, {}); return true; } @@ -90,41 +108,32 @@ bool rna_CurvesGeometry_resize_curves(blender::bke::CurvesGeometry &curves, return false; } IndexMaskMemory memory; - IndexMask curves_to_resize; - if (indices_ptr != nullptr) { - if (indices_num != sizes_num) { - BKE_report(reports, RPT_ERROR, "Length of sizes and length of indices must be the same"); - return false; - } - const Span indices(indices_ptr, indices_num); - if (std::any_of(indices.begin(), indices.end(), [&](const int index) { - return !curves.curves_range().contains(index); - })) - { - BKE_report(reports, RPT_ERROR, "Indices must be in range"); - return false; - } - if (!std::is_sorted(indices.begin(), indices.end())) { - BKE_report(reports, RPT_ERROR, "Indices must be sorted in ascending order"); - return false; - } - if (std::adjacent_find(indices.begin(), indices.end(), std::greater_equal()) != - indices.end()) - { - BKE_report(reports, RPT_ERROR, "Indices can't have duplicates"); - return false; - } - curves_to_resize = IndexMask::from_indices(indices, memory); + const std::optional curves_to_resize = rna_indices_to_mask( + curves.curves_range(), indices_ptr, indices_num, *reports, memory); + if (!curves_to_resize) { + return false; } - else { - if (sizes_num != curves.curves_num()) { - BKE_report(reports, RPT_ERROR, "Length of sizes and number of strokes must be the same"); - return false; - } - curves_to_resize = curves.curves_range(); + if (curves_to_resize->size() != sizes_num) { + BKE_report(reports, RPT_ERROR, "Length of sizes must be the same as the selection size"); + return false; } + ed::curves::resize_curves(curves, *curves_to_resize, {sizes_ptr, sizes_num}); + return true; +} - ed::curves::resize_curves(curves, curves_to_resize, {sizes_ptr, sizes_num}); +bool rna_CurvesGeometry_set_types(blender::bke::CurvesGeometry &curves, + ReportList *reports, + const int type, + const int *indices_ptr, + const int indices_num) +{ + IndexMaskMemory memory; + const std::optional selection = rna_indices_to_mask( + curves.curves_range(), indices_ptr, indices_num, *reports, memory); + if (!selection) { + return false; + } + curves.fill_curve_types(*selection, CurveType(type)); return true; } @@ -188,6 +197,24 @@ static void rna_Curves_resize_curves(Curves *curves_id, } } +static void rna_Curves_set_types(Curves *curves_id, + ReportList *reports, + const int type, + const int *indices_ptr, + const int indices_num) +{ + using namespace blender; + bke::CurvesGeometry &curves = curves_id->geometry.wrap(); + if (!rna_CurvesGeometry_set_types(curves, reports, type, indices_ptr, 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); + } +} + #else void RNA_api_curves(StructRNA *srna) @@ -255,6 +282,24 @@ void RNA_api_curves(StructRNA *srna) 0, 10000); RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0)); + + 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 " + "types with the given curve indices."); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_enum(func, "type", rna_enum_curves_type_items, CURVE_TYPE_CATMULL_ROM, "Type", ""); + parm = RNA_def_int_array(func, + "indices", + 1, + nullptr, + 0, + INT_MAX, + "Indices", + "The indices of the curves to resize", + 0, + INT_MAX); + RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0)); } #endif diff --git a/source/blender/makesrna/intern/rna_curves_utils.hh b/source/blender/makesrna/intern/rna_curves_utils.hh index aa521056ba9..abe317d4623 100644 --- a/source/blender/makesrna/intern/rna_curves_utils.hh +++ b/source/blender/makesrna/intern/rna_curves_utils.hh @@ -35,4 +35,10 @@ bool rna_CurvesGeometry_resize_curves(blender::bke::CurvesGeometry &curves, const int *indices_ptr, int indices_num); +bool rna_CurvesGeometry_set_types(blender::bke::CurvesGeometry &curves, + ReportList *reports, + int type, + const int *indices_ptr, + int indices_num); + #endif diff --git a/source/blender/makesrna/intern/rna_grease_pencil_api.cc b/source/blender/makesrna/intern/rna_grease_pencil_api.cc index 7014c90ed4a..b847e76cdd3 100644 --- a/source/blender/makesrna/intern/rna_grease_pencil_api.cc +++ b/source/blender/makesrna/intern/rna_grease_pencil_api.cc @@ -10,6 +10,7 @@ #include "DNA_scene_types.h" #include "RNA_define.hh" +#include "RNA_enum_types.hh" #include "WM_api.hh" @@ -107,6 +108,26 @@ static void rna_GreasePencilDrawing_resize_curves(ID *grease_pencil_id, } } +static void rna_GreasePencilDrawing_set_types(ID *grease_pencil_id, + GreasePencilDrawing *drawing_ptr, + ReportList *reports, + const int type, + const int *indices_ptr, + const int indices_num) +{ + using namespace blender; + bke::greasepencil::Drawing &drawing = drawing_ptr->wrap(); + bke::CurvesGeometry &curves = drawing.strokes_for_write(); + if (!rna_CurvesGeometry_set_types(curves, reports, type, indices_ptr, indices_num)) { + return; + } + /* 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_tag_positions_changed(GreasePencilDrawing *drawing_ptr) { drawing_ptr->wrap().tag_positions_changed(); @@ -490,6 +511,24 @@ void RNA_api_grease_pencil_drawing(StructRNA *srna) 10000); RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0)); + 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 " + "types with the given curve indices."); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_enum(func, "type", rna_enum_curves_type_items, CURVE_TYPE_CATMULL_ROM, "Type", ""); + parm = RNA_def_int_array(func, + "indices", + 1, + nullptr, + 0, + INT_MAX, + "Indices", + "The indices of the curves to resize", + 0, + INT_MAX); + RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0)); + func = RNA_def_function( srna, "tag_positions_changed", "rna_GreasePencilDrawing_tag_positions_changed"); RNA_def_function_ui_description(