Blender V5.0
rna_curves_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_curves_types.h"
10
11#include "RNA_define.hh"
12
13#include "RNA_enum_types.hh"
14
15#include "rna_internal.hh" /* own include */
16
17#ifdef RNA_RUNTIME
18
19# include "BKE_curves.hh"
21# include "BKE_report.hh"
22
23# include "BLI_index_mask.hh"
24# include "BLI_set.hh"
25
26# include "ED_curves.hh"
27
28# include "DEG_depsgraph.hh"
29
30# include "WM_api.hh"
31
32# include "rna_curves_utils.hh"
33
34/* Common `CurvesGeometry` API functions. */
35
39using blender::Span;
40
41bool rna_CurvesGeometry_add_curves(blender::bke::CurvesGeometry &curves,
42 ReportList *reports,
43 const int *sizes_ptr,
44 const int sizes_num)
45{
46 using namespace blender;
47 if (std::any_of(sizes_ptr, sizes_ptr + sizes_num, [](const int size) { return size < 1; })) {
48 BKE_report(reports, RPT_ERROR, "Curve sizes must be greater than zero");
49 return false;
50 }
51
52 ed::curves::add_curves(curves, {sizes_ptr, sizes_num});
53 curves.tag_topology_changed();
54 return true;
55}
56
57static std::optional<IndexMask> rna_indices_to_mask(const IndexRange universe,
58 const int *indices_ptr,
59 const int indices_num,
60 ReportList &reports,
61 IndexMaskMemory &memory)
62{
63 if (!indices_ptr) {
64 return IndexMask(universe);
65 }
66 const Span<int> indices(indices_ptr, indices_num);
67 if (std::any_of(indices.begin(), indices.end(), [&](const int index) {
68 return !universe.contains(index);
69 }))
70 {
71 BKE_report(&reports, RPT_ERROR, "Indices must be in range");
72 return std::nullopt;
73 }
74 if (!std::is_sorted(indices.begin(), indices.end())) {
75 BKE_report(&reports, RPT_ERROR, "Indices must be sorted in ascending order");
76 return std::nullopt;
77 }
78 if (std::adjacent_find(indices.begin(), indices.end(), std::greater_equal<>()) != indices.end())
79 {
80 BKE_report(&reports, RPT_ERROR, "Indices cannot have duplicates");
81 return std::nullopt;
82 }
83 return IndexMask::from_indices(indices, memory);
84}
85
86bool rna_CurvesGeometry_remove_curves(blender::bke::CurvesGeometry &curves,
87 ReportList *reports,
88 const int *indices_ptr,
89 const int indices_num)
90{
91 using namespace blender;
92 IndexMaskMemory memory;
93 const std::optional<IndexMask> curves_to_delete = rna_indices_to_mask(
94 curves.curves_range(), indices_ptr, indices_num, *reports, memory);
95 if (!curves_to_delete) {
96 return false;
97 }
98 curves.remove_curves(*curves_to_delete, {});
99 return true;
100}
101
102bool rna_CurvesGeometry_resize_curves(blender::bke::CurvesGeometry &curves,
103 ReportList *reports,
104 const int *sizes_ptr,
105 const int sizes_num,
106 const int *indices_ptr,
107 const int indices_num)
108{
109 using namespace blender;
110 const Span<int> new_sizes(sizes_ptr, sizes_num);
111 if (std::any_of(new_sizes.begin(), new_sizes.end(), [](const int size) { return size < 1; })) {
112 BKE_report(reports, RPT_ERROR, "Sizes must be greater than zero");
113 return false;
114 }
115 IndexMaskMemory memory;
116 const std::optional<IndexMask> curves_to_resize = rna_indices_to_mask(
117 curves.curves_range(), indices_ptr, indices_num, *reports, memory);
118 if (!curves_to_resize) {
119 return false;
120 }
121 if (curves_to_resize->size() != sizes_num) {
122 BKE_report(reports, RPT_ERROR, "Length of sizes must be the same as the selection size");
123 return false;
124 }
125 ed::curves::resize_curves(curves, *curves_to_resize, {sizes_ptr, sizes_num});
126 return true;
127}
128
129bool rna_CurvesGeometry_reorder_curves(blender::bke::CurvesGeometry &curves,
130 ReportList *reports,
131 const int *reorder_indices_ptr,
132 const int reorder_indices_num)
133{
134 using namespace blender;
135 const Span<int> new_to_old_indices_map(reorder_indices_ptr, reorder_indices_num);
136 if (curves.curves_num() != reorder_indices_num) {
138 reports, RPT_ERROR, "Length of reorder indices must be the same as the number of curves");
139 return false;
140 }
141 if (std::any_of(new_to_old_indices_map.begin(),
142 new_to_old_indices_map.end(),
143 [&](const int index) { return !curves.curves_range().contains(index); }))
144 {
145 BKE_report(reports, RPT_ERROR, "Reorder indices must be valid");
146 return false;
147 }
148 if (Set(new_to_old_indices_map).size() != reorder_indices_num) {
149 BKE_report(reports, RPT_ERROR, "Reorder indices must not have duplicates");
150 return false;
151 }
152 ed::curves::reorder_curves(curves, new_to_old_indices_map);
153 return true;
154}
155
156bool rna_CurvesGeometry_set_types(blender::bke::CurvesGeometry &curves,
157 ReportList *reports,
158 const int type,
159 const int *indices_ptr,
160 const int indices_num)
161{
162 IndexMaskMemory memory;
163 const std::optional<IndexMask> selection = rna_indices_to_mask(
164 curves.curves_range(), indices_ptr, indices_num, *reports, memory);
165 if (!selection) {
166 return false;
167 }
168 curves.fill_curve_types(*selection, CurveType(type));
169 return true;
170}
171
172/* Curves API functions. */
173
174static void rna_Curves_add_curves(Curves *curves_id,
175 ReportList *reports,
176 const int *sizes,
177 const int sizes_num)
178{
179 using namespace blender;
180 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
181 if (!rna_CurvesGeometry_add_curves(curves, reports, sizes, sizes_num)) {
182 return;
183 }
184
185 /* Avoid updates for importers creating curves. */
186 if (curves_id->id.us > 0) {
189 }
190}
191
192static void rna_Curves_remove_curves(Curves *curves_id,
193 ReportList *reports,
194 const int *indices_ptr,
195 const int indices_num)
196{
197 using namespace blender;
198 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
199 if (!rna_CurvesGeometry_remove_curves(curves, reports, indices_ptr, indices_num)) {
200 return;
201 }
202
203 /* Avoid updates for importers creating curves. */
204 if (curves_id->id.us > 0) {
207 }
208}
209
210static void rna_Curves_resize_curves(Curves *curves_id,
211 ReportList *reports,
212 const int *sizes_ptr,
213 const int sizes_num,
214 const int *indices_ptr,
215 const int indices_num)
216{
217 using namespace blender;
218 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
219 if (!rna_CurvesGeometry_resize_curves(
220 curves, reports, sizes_ptr, sizes_num, indices_ptr, indices_num))
221 {
222 return;
223 }
224
225 /* Avoid updates for importers creating curves. */
226 if (curves_id->id.us > 0) {
229 }
230}
231
232static void rna_Curves_reorder_curves(Curves *curves_id,
233 ReportList *reports,
234 const int *reorder_indices_ptr,
235 const int reorder_indices_num)
236{
237 using namespace blender;
238 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
239 if (!rna_CurvesGeometry_reorder_curves(
240 curves, reports, reorder_indices_ptr, reorder_indices_num))
241 {
242 return;
243 }
244
245 /* Avoid updates for importers creating curves. */
246 if (curves_id->id.us > 0) {
249 }
250}
251
252static void rna_Curves_set_types(Curves *curves_id,
253 ReportList *reports,
254 const int type,
255 const int *indices_ptr,
256 const int indices_num)
257{
258 using namespace blender;
259 bke::CurvesGeometry &curves = curves_id->geometry.wrap();
260 if (!rna_CurvesGeometry_set_types(curves, reports, type, indices_ptr, indices_num)) {
261 return;
262 }
263 /* Avoid updates for importers creating curves. */
264 if (curves_id->id.us > 0) {
267 }
268}
269
270static const char *rna_Curves_unit_test_compare(Curves *curves1, Curves *curves2, float threshold)
271{
272 using namespace blender::bke::compare_geometry;
273
274 const std::optional<GeoMismatch> mismatch = compare_curves(
275 curves1->geometry.wrap(), curves2->geometry.wrap(), threshold);
276
277 if (!mismatch) {
278 return "Same";
279 }
280
281 return mismatch_to_string(mismatch.value());
282}
283
284#else
285
287{
288 FunctionRNA *func;
289 PropertyRNA *parm;
290
291 func = RNA_def_function(srna, "add_curves", "rna_Curves_add_curves");
293 parm = RNA_def_int_array(func,
294 "sizes",
295 1,
296 nullptr,
297 0,
298 INT_MAX,
299 "Sizes",
300 "The number of points in each curve",
301 1,
302 10000);
304
305 func = RNA_def_function(srna, "remove_curves", "rna_Curves_remove_curves");
307 "Remove all curves. If indices are provided, remove only the "
308 "curves with the given indices.");
310 parm = RNA_def_int_array(func,
311 "indices",
312 1,
313 nullptr,
314 0,
315 INT_MAX,
316 "Indices",
317 "The indices of the curves to remove",
318 0,
319 10000);
321
322 func = RNA_def_function(srna, "resize_curves", "rna_Curves_resize_curves");
324 func,
325 "Resize all existing curves. If indices are provided, resize only the curves with the given "
326 "indices. If the new size for a curve is smaller, the curve is trimmed. If "
327 "the new size for a curve is larger, the new end values are default initialized.");
329 parm = RNA_def_int_array(func,
330 "sizes",
331 1,
332 nullptr,
333 1,
334 INT_MAX,
335 "Sizes",
336 "The number of points in each curve",
337 1,
338 10000);
340 parm = RNA_def_int_array(func,
341 "indices",
342 1,
343 nullptr,
344 0,
345 INT_MAX,
346 "Indices",
347 "The indices of the curves to resize",
348 0,
349 10000);
351
352 func = RNA_def_function(srna, "reorder_curves", "rna_Curves_reorder_curves");
353 RNA_def_function_ui_description(func, "Reorder the curves by the new indices.");
355 parm = RNA_def_int_array(func,
356 "new_indices",
357 1,
358 nullptr,
359 0,
360 INT_MAX,
361 "New indices",
362 "The new index for each of the curves",
363 0,
364 10000);
366
367 func = RNA_def_function(srna, "set_types", "rna_Curves_set_types");
369 "Set the curve type. If indices are provided, set only the "
370 "types with the given curve indices.");
373 parm = RNA_def_int_array(func,
374 "indices",
375 1,
376 nullptr,
377 0,
378 INT_MAX,
379 "Indices",
380 "The indices of the curves to resize",
381 0,
382 INT_MAX);
384
385 func = RNA_def_function(srna, "unit_test_compare", "rna_Curves_unit_test_compare");
386 RNA_def_pointer(func, "curves", "Curves", "", "Curves to compare to");
388 "threshold",
389 FLT_EPSILON * 60,
390 0.0f,
391 FLT_MAX,
392 "Threshold",
393 "Comparison tolerance threshold",
394 0.0f,
395 FLT_MAX);
396 /* return value */
397 parm = RNA_def_string(
398 func, "result", "nothing", 64, "Return value", "String description of result of comparison");
399 RNA_def_function_return(func, parm);
400}
401
402#endif
Low-level operations for curves.
@ RPT_ERROR
Definition BKE_report.hh:39
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
ParameterFlag
Definition RNA_types.hh:544
@ PARM_REQUIRED
Definition RNA_types.hh:545
@ FUNC_USE_REPORTS
Definition RNA_types.hh:914
@ PROP_DYNAMIC
Definition RNA_types.hh:428
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
IndexRange curves_range() const
void remove_curves(const IndexMask &curves_to_delete, const AttributeFilter &attribute_filter)
void fill_curve_types(CurveType type)
static ushort indices[]
std::optional< GeoMismatch > compare_curves(const CurvesGeometry &curves1, const CurvesGeometry &curves2, float threshold)
Checks if the two curves geometries are different, returning the type of mismatch if any....
const char * mismatch_to_string(const GeoMismatch &mismatch)
void resize_curves(bke::CurvesGeometry &curves, const IndexMask &curves_to_resize, const Span< int > new_sizes)
void add_curves(bke::CurvesGeometry &curves, const Span< int > new_sizes)
void reorder_curves(bke::CurvesGeometry &curves, const Span< int > old_by_new_indices_map)
const EnumPropertyItem rna_enum_curves_type_items[]
Definition rna_curves.cc:24
void RNA_api_curves(StructRNA *srna)
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
void RNA_def_function_return(FunctionRNA *func, PropertyRNA *ret)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
FunctionRNA * RNA_def_function(StructRNA *srna, const char *identifier, const char *call)
PropertyRNA * RNA_def_pointer(StructOrFunctionRNA *cont_, const char *identifier, const char *type, const char *ui_name, const char *ui_description)
void RNA_def_function_ui_description(FunctionRNA *func, const char *description)
void RNA_def_function_flag(FunctionRNA *func, int flag)
void RNA_def_parameter_flags(PropertyRNA *prop, PropertyFlag flag_property, ParameterFlag flag_parameter)
#define FLT_MAX
Definition stdcycles.h:14
CurvesGeometry geometry
int us
Definition DNA_ID.h:443
void WM_main_add_notifier(uint type, void *reference)