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
This commit is contained in:
@@ -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<IndexMask> 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<int> 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<int>()) !=
|
||||
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<int> 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<int>()) !=
|
||||
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<IndexMask> 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<int> 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<int>()) !=
|
||||
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<IndexMask> 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<IndexMask> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user