Blender V5.0
rna_access.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstddef>
10#include <cstdint>
11#include <cstring>
12#include <limits>
13#include <sstream>
14
15#include <fmt/format.h>
16
17#include "MEM_guardedalloc.h"
18
19#include "DNA_ID.h"
20#include "DNA_anim_types.h"
21#include "DNA_scene_types.h"
23
24#include "BLI_dynstr.h"
25#include "BLI_ghash.h"
26#include "BLI_listbase.h"
27#include "BLI_math_base.h"
28#include "BLI_mutex.hh"
29#include "BLI_string.h"
30#include "BLI_utildefines.h"
31
32#include "BLT_translation.hh"
33
34#include "BKE_anim_data.hh"
35#include "BKE_collection.hh"
36#include "BKE_context.hh"
37#include "BKE_fcurve.hh"
38#include "BKE_global.hh"
39#include "BKE_idprop.hh"
40#include "BKE_idtype.hh"
41#include "BKE_lib_id.hh"
42#include "BKE_lib_override.hh"
43#include "BKE_library.hh"
44#include "BKE_main.hh"
45#include "BKE_node.hh"
46#include "BKE_report.hh"
47
48#include "CLG_log.h"
49
50#include "DEG_depsgraph.hh"
52
53#include "RNA_access.hh"
54#include "RNA_define.hh"
55#include "RNA_enum_types.hh"
56#include "RNA_path.hh"
57#include "RNA_types.hh"
58
59#include "UI_resources.hh"
60
61#include "WM_api.hh"
62#include "WM_message.hh"
63
64/* flush updates */
65#include "WM_types.hh"
66
67#ifdef WITH_PYTHON
68# include "BPY_extern.hh"
69#endif
70
72#include "rna_internal.hh"
73
74static CLG_LogRef LOG = {"rna.access"};
75
81#define USE_INT_IDPROPS_FOR_BOOLEAN_RNA_PROP
82
83/* Init/Exit */
84
85/* NOTE: Initializing this object here is fine for now, as it should not allocate any memory. */
86extern const PointerRNA PointerRNA_NULL = {};
87
89{
90 StructRNA *srna;
91
92 BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
93 BLENDER_RNA.structs_len = 0;
94
95 for (srna = static_cast<StructRNA *>(BLENDER_RNA.structs.first); srna;
96 srna = static_cast<StructRNA *>(srna->cont.next))
97 {
98 if (!srna->cont.prop_lookup_set) {
99 srna->cont.prop_lookup_set =
100 MEM_new<blender::CustomIDVectorSet<PropertyRNA *, PropertyRNAIdentifierGetter>>(
101 __func__);
102
103 LISTBASE_FOREACH (PropertyRNA *, prop, &srna->cont.properties) {
104 if (!(prop->flag_internal & PROP_INTERN_BUILTIN)) {
105 srna->cont.prop_lookup_set->add(prop);
106 }
107 }
108 }
110 BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
111 BLENDER_RNA.structs_len += 1;
112 }
113}
114
116{
117#ifdef WITH_PYTHON
118 StructRNA *srna;
119
120 for (srna = static_cast<StructRNA *>(BLENDER_RNA.structs.first); srna;
121 srna = static_cast<StructRNA *>(srna->cont.next))
122 {
123 /* NOTE(@ideasman42): each call locks the Python's GIL. Only locking/unlocking once
124 * is possible but gives barely measurable speedup (< ~1millisecond) so leave as-is. */
126 }
127#endif
128}
129
131{
132 StructRNA *srna;
133
134 for (srna = static_cast<StructRNA *>(BLENDER_RNA.structs.first); srna;
135 srna = static_cast<StructRNA *>(srna->cont.next))
136 {
137 MEM_SAFE_DELETE(srna->cont.prop_lookup_set);
138 }
139
141}
142
143/* Pointer */
144
146{
147 while (r_ptr.type->refine) {
148 StructRNA *type = r_ptr.type->refine(&r_ptr);
149 if (type == r_ptr.type) {
150 break;
151 }
152 r_ptr.type = type;
153 }
154}
155
157 StructRNA *type,
158 void *data,
159 PointerRNA &r_ptr)
160{
161 if (data) {
162 if (type && type->flag & STRUCT_ID) {
163 /* Currently, assume that an ID PointerRNA never has an ancestor.
164 * NOTE: This may become an issue for embedded IDs in the future, see also
165 * #PointerRNA::ancestors docs. */
166 r_ptr = {static_cast<ID *>(data), type, data};
167 }
168 else {
169 r_ptr = {parent.owner_id, type, data, parent};
170 }
171 rna_pointer_refine(r_ptr);
172 }
173 else {
174 r_ptr = {};
175 }
176}
177
179{
180 return {nullptr, &RNA_BlendData, main};
181}
182
184{
185 if (id) {
188 return ptr;
189 }
190
191 return PointerRNA_NULL;
192}
193
195{
196 PointerRNA ptr{id, type, data};
197
198 if (data) {
200 }
201
202 return ptr;
203}
204
206{
209 return result;
210}
211
219
221{
222 if (ancestor_idx >= ptr.ancestors.size()) {
224 return {};
225 }
226
227 /* NOTE: No call to `rna_pointer_refine` should be needed here, as ancestors info should have
228 * been created from already refined PointerRNA data. */
229 PointerRNA ancestor_ptr{ptr.owner_id,
230 ptr.ancestors[ancestor_idx].type,
231 ptr.ancestors[ancestor_idx].data,
232 ptr.ancestors.as_span().slice(0, ancestor_idx)};
233#ifndef NDEBUG
234 StructRNA *type = ancestor_ptr.type;
235 rna_pointer_refine(ancestor_ptr);
236 BLI_assert(type == ancestor_ptr.type);
237#endif
238
239 return ancestor_ptr;
240}
241
243{
244 return (ptr->data == nullptr) || (ptr->type == nullptr);
245}
246
248{
249 PointerRNA ptr = {};
250 ptr.owner_id = nullptr;
251 ptr.type = &RNA_BlenderRNA;
252 ptr.data = &BLENDER_RNA;
253 return ptr;
254}
255
257{
258#if 0 /* works but this case if covered by more general code below. */
259 if (RNA_struct_is_ID(ptr->type)) {
260 /* simple case */
261 return RNA_id_pointer_create(ptr->owner_id);
262 }
263 else
264#endif
265 {
266 PointerRNA ptr_result{*ptr};
267 PointerRNA t_ptr{*ptr};
268 StructRNA *base;
269
270 for (base = ptr->type->base; base; base = base->base) {
271 t_ptr.type = base;
272 rna_pointer_refine(t_ptr);
273 if (t_ptr.type && t_ptr.type != ptr->type) {
274 ptr_result = t_ptr;
275 }
276 }
277 return ptr_result;
278 }
279}
280
281/* ID Properties */
282
284{
285 /* so the property is seen as 'set' by rna */
286 idprop->flag &= ~IDP_FLAG_GHOST;
287}
288
290{
291 StructRNA *type = ptr->type;
292 if (type == nullptr) {
293 return nullptr;
294 }
295 if (type->idproperties == nullptr) {
296 return nullptr;
297 }
298
299 return type->idproperties(ptr);
300}
301
303{
304 IDProperty **property_ptr = RNA_struct_idprops_p(ptr);
305 if (property_ptr == nullptr) {
306 return nullptr;
307 }
308
309 if (create && *property_ptr == nullptr) {
310 *property_ptr =
311 blender::bke::idprop::create_group("user_properties", IDP_FLAG_STATIC_TYPE).release();
312 }
313
314 return *property_ptr;
315}
316
318{
319 return (srna && srna->idproperties);
320}
321
323{
324 IDProperty *group = RNA_struct_idprops(ptr, false);
325
326 if (!group) {
327 return nullptr;
328 }
329 if (group->type == IDP_GROUP) {
330 return IDP_GetPropertyFromGroup(group, name);
331 }
332
333 /* Not sure why that happens sometimes, with nested properties... */
334 /* Seems to be actually array prop, name is usually "0"... To be sorted out later. */
335#if 0
336 printf("Got unexpected IDProp container when trying to retrieve %s: %d\n", name, group->type);
337#endif
338
339 return nullptr;
340}
341
343{
344 StructRNA *type = ptr->type;
345 if (type == nullptr) {
346 return nullptr;
347 }
348 if (type->system_idproperties == nullptr) {
349 return nullptr;
350 }
351
352 return type->system_idproperties(ptr);
353}
354
356{
358 if (property_ptr == nullptr) {
359 return nullptr;
360 }
361
362 if (create && *property_ptr == nullptr) {
363 *property_ptr =
364 blender::bke::idprop::create_group("system_properties", IDP_FLAG_STATIC_TYPE).release();
365 }
366
367 return *property_ptr;
368}
369
371{
372 return (srna && srna->system_idproperties);
373}
374
376{
378
379 if (!group) {
380 return nullptr;
381 }
382
383 if (group->type == IDP_GROUP) {
384 return IDP_GetPropertyFromGroup(group, name);
385 }
386
387 /* Not sure why that happens sometimes, with nested properties... */
388 /* Seems to be actually array prop, name is usually "0"... To be sorted out later. */
389#if 0
390 printf("Got unexpected IDProp container when trying to retrieve %s: %d\n", name, group->type);
391#endif
392
393 return nullptr;
394}
395
397{
399
400 if (group) {
401 IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
402 if (idprop) {
403 IDP_FreeFromGroup(group, idprop);
404 }
405 }
406}
407
409{
410 if (prop->magic == RNA_MAGIC) {
411 int arraylen[RNA_MAX_ARRAY_DIMENSION];
412 return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) :
413 int(prop->totarraylength);
414 }
415 IDProperty *idprop = (IDProperty *)prop;
416
417 if (idprop->type == IDP_ARRAY) {
418 return idprop->len;
419 }
420 return 0;
421}
422
424{
425 if (prop->magic == RNA_MAGIC) {
426 return (prop->getlength || prop->totarraylength);
427 }
428 IDProperty *idprop = (IDProperty *)prop;
429
430 return (idprop->type == IDP_ARRAY);
431}
432
434 PropertyRNA *prop,
435 int length[])
436{
437 if (prop->magic == RNA_MAGIC) {
438 if (prop->getlength) {
439 prop->getlength(ptr, length);
440 }
441 else {
442 memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
443 }
444 }
445 else {
446 IDProperty *idprop = (IDProperty *)prop;
447
448 if (idprop->type == IDP_ARRAY) {
449 length[0] = idprop->len;
450 }
451 else {
452 length[0] = 0;
453 }
454 }
455}
456
458{
459 /* this verifies if the idproperty actually matches the property
460 * description and otherwise removes it. this is to ensure that
461 * rna property access is type safe, e.g. if you defined the rna
462 * to have a certain array length you can count on that staying so */
463
464 switch (idprop->type) {
465 case IDP_IDPARRAY:
466 if (prop->type != PROP_COLLECTION) {
467 return false;
468 }
469 break;
470 case IDP_ARRAY:
471 if (rna_ensure_property_array_length(ptr, prop) != idprop->len) {
472 return false;
473 }
474
475 if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT) {
476 return false;
477 }
478 if (idprop->subtype == IDP_BOOLEAN && prop->type != PROP_BOOLEAN) {
479 return false;
480 }
481 if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) {
482 return false;
483 }
484
485 break;
486 case IDP_INT:
487 if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) {
488 return false;
489 }
490 break;
491 case IDP_BOOLEAN:
492 if (prop->type != PROP_BOOLEAN) {
493 return false;
494 }
495 break;
496 case IDP_FLOAT:
497 case IDP_DOUBLE:
498 if (prop->type != PROP_FLOAT) {
499 return false;
500 }
501 break;
502 case IDP_STRING:
503 if (prop->type != PROP_STRING) {
504 return false;
505 }
506 break;
507 case IDP_GROUP:
508 case IDP_ID:
509 if (prop->type != PROP_POINTER) {
510 return false;
511 }
512 break;
513 default:
514 return false;
515 }
516
517 return true;
518}
519
521 &rna_PropertyGroupItem_string,
522 &rna_PropertyGroupItem_int,
523 &rna_PropertyGroupItem_float,
524 nullptr,
525 nullptr,
526 nullptr,
527 &rna_PropertyGroupItem_group,
528 &rna_PropertyGroupItem_id,
529 &rna_PropertyGroupItem_double,
530 &rna_PropertyGroupItem_idp_array,
531 &rna_PropertyGroupItem_bool,
532};
533
535 nullptr,
536 &rna_PropertyGroupItem_int_array,
537 &rna_PropertyGroupItem_float_array,
538 nullptr,
539 nullptr,
540 nullptr,
541 &rna_PropertyGroupItem_collection,
542 nullptr,
543 &rna_PropertyGroupItem_double_array,
544 nullptr,
545 &rna_PropertyGroupItem_bool_array,
546};
547
550 PropertyRNAOrID *r_prop_rna_or_id)
551{
552 /* This is quite a hack, but avoids some complexity in the API. we
553 * pass IDProperty structs as PropertyRNA pointers to the outside.
554 * We store some bytes in PropertyRNA structs that allows us to
555 * distinguish it from IDProperty structs. If it is an ID property,
556 * we look up an IDP PropertyRNA based on the type, and set the data
557 * pointer to the IDProperty. */
558 *r_prop_rna_or_id = {};
559
560 r_prop_rna_or_id->ptr = ptr;
561 r_prop_rna_or_id->rawprop = prop;
562
563 if (prop->magic == RNA_MAGIC) {
564 r_prop_rna_or_id->rnaprop = prop;
565 r_prop_rna_or_id->identifier = prop->identifier;
566
567 r_prop_rna_or_id->is_array = prop->getlength || prop->totarraylength;
568 if (r_prop_rna_or_id->is_array) {
569 int arraylen[RNA_MAX_ARRAY_DIMENSION];
570 r_prop_rna_or_id->array_len = (prop->getlength && ptr->data) ?
571 uint(prop->getlength(ptr, arraylen)) :
572 prop->totarraylength;
573 }
574
575 if (prop->flag & PROP_IDPROPERTY) {
577
578 if (idprop != nullptr && !rna_idproperty_verify_valid(ptr, prop, idprop)) {
580
581 IDP_FreeFromGroup(group, idprop);
582 idprop = nullptr;
583 }
584
585 r_prop_rna_or_id->idprop = idprop;
586 r_prop_rna_or_id->is_rna_storage_idprop = true;
587 r_prop_rna_or_id->is_set = idprop != nullptr && (idprop->flag & IDP_FLAG_GHOST) == 0;
588 }
589 else {
590 /* Full static RNA properties are always set. */
591 r_prop_rna_or_id->is_set = true;
592 }
593 }
594 else {
595 IDProperty *idprop = (IDProperty *)prop;
596 /* Given prop may come from the custom properties of another data, ensure we get the one from
597 * given data ptr. */
598 IDProperty *idprop_evaluated = rna_idproperty_find(ptr, idprop->name);
599 if (idprop_evaluated != nullptr && idprop->type != idprop_evaluated->type) {
600 idprop_evaluated = nullptr;
601 }
602
603 r_prop_rna_or_id->idprop = idprop_evaluated;
604 r_prop_rna_or_id->is_idprop = true;
605 /* Full IDProperties are always set, if it exists. */
606 r_prop_rna_or_id->is_set = (idprop_evaluated != nullptr);
607
608 r_prop_rna_or_id->identifier = idprop->name;
609 if (idprop->type == IDP_ARRAY) {
610 r_prop_rna_or_id->rnaprop = arraytypemap[int(idprop->subtype)];
611 r_prop_rna_or_id->is_array = true;
612 r_prop_rna_or_id->array_len = idprop_evaluated != nullptr ? uint(idprop_evaluated->len) : 0;
613 }
614 else {
615 /* Special case for int properties with enum items, these are displayed as a PROP_ENUM. */
616 if (idprop->type == IDP_INT) {
617 const IDPropertyUIDataInt *ui_data_int = reinterpret_cast<IDPropertyUIDataInt *>(
618 idprop->ui_data);
619 if (ui_data_int && ui_data_int->enum_items_num > 0) {
620 r_prop_rna_or_id->rnaprop = &rna_PropertyGroupItem_enum;
621 return;
622 }
623 }
624 r_prop_rna_or_id->rnaprop = typemap[int(idprop->type)];
625 }
626 }
627}
628
630{
631 PropertyRNAOrID prop_rna_or_id;
632
633 rna_property_rna_or_id_get(*prop, ptr, &prop_rna_or_id);
634
635 *prop = prop_rna_or_id.rnaprop;
636 return prop_rna_or_id.idprop;
637}
638
640{
641 /* the quick version if we don't need the idproperty */
642
643 if (prop->magic == RNA_MAGIC) {
644 return prop;
645 }
646
647 {
648 IDProperty *idprop = (IDProperty *)prop;
649
650 if (idprop->type == IDP_ARRAY) {
651 return arraytypemap[int(idprop->subtype)];
652 }
653 /* Special case for int properties with enum items, these are displayed as a PROP_ENUM. */
654 if (idprop->type == IDP_INT) {
655 const IDPropertyUIDataInt *ui_data_int = reinterpret_cast<IDPropertyUIDataInt *>(
656 idprop->ui_data);
657 if (ui_data_int && ui_data_int->enum_items_num > 0) {
658 return &rna_PropertyGroupItem_enum;
659 }
660 }
661 return typemap[int(idprop->type)];
662 }
663}
664
665static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
666{
667 if (prop->magic == RNA_MAGIC) {
668 return prop->identifier;
669 }
670 return ((const IDProperty *)prop)->name;
671}
672
673static const char *rna_ensure_property_description(const PropertyRNA *prop)
674{
675 if (prop->magic == RNA_MAGIC) {
676 return prop->description;
677 }
678
679 const IDProperty *idprop = (const IDProperty *)prop;
680 if (idprop->ui_data) {
681 const IDPropertyUIData *ui_data = idprop->ui_data;
682 return ui_data->description;
683 }
684
685 return "";
686}
687
688static const char *rna_ensure_property_name(const PropertyRNA *prop)
689{
690 const char *name;
691
692 if (prop->magic == RNA_MAGIC) {
693 name = prop->name;
694 }
695 else {
696 name = ((const IDProperty *)prop)->name;
697 }
698
699 return name;
700}
701
702/* Structs */
703
704StructRNA *RNA_struct_find(const char *identifier)
705{
706 return static_cast<StructRNA *>(BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier));
707}
708
709const char *RNA_struct_identifier(const StructRNA *type)
710{
711 return type->identifier;
712}
713
714const char *RNA_struct_ui_name(const StructRNA *type)
715{
716 return CTX_IFACE_(type->translation_context, type->name);
717}
718
719const char *RNA_struct_ui_name_raw(const StructRNA *type)
720{
721 return type->name;
722}
723
725{
726 if (type) {
727 return type->icon;
728 }
729 return ICON_DOT;
730}
731
732const char *RNA_struct_ui_description(const StructRNA *type)
733{
734 return TIP_(type->description);
735}
736
738{
739 return type->description;
740}
741
743{
744 return type->translation_context;
745}
746
748{
749 return type->nameproperty;
750}
751
753{
754 return type->prop_tag_defines;
755}
756
761
763{
764 return type->base;
765}
766
767const StructRNA *RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
768{
769 while (type) {
770 if (type->base == parent_type) {
771 return type;
772 }
773 type = type->base;
774 }
775 return nullptr;
776}
777
779{
780 return (type->flag & STRUCT_ID) != 0;
781}
782
784{
785 return (type->flag & STRUCT_UNDO) != 0;
786}
787
792
797
799{
800 return (type->flag & STRUCT_NO_IDPROPERTIES) == 0 && type->system_idproperties != nullptr;
801}
802
803bool RNA_struct_system_idprops_unset(PointerRNA *ptr, const char *identifier)
804{
806
807 if (group) {
808 IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
809 if (idp) {
810 IDP_FreeFromGroup(group, idp);
811
812 return true;
813 }
814 }
815 return false;
816}
817
818bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
819{
820 const StructRNA *base;
821
822 if (srna == &RNA_AnyType) {
823 return true;
824 }
825
826 if (!type) {
827 return false;
828 }
829
830 /* ptr->type is always maximally refined */
831 for (base = type; base; base = base->base) {
832 if (base == srna) {
833 return true;
834 }
835 }
836
837 return false;
838}
839
841{
842 if (identifier[0] == '[' && identifier[1] == '"') {
843 /* id prop lookup, not so common */
844 PropertyRNA *prop_test = nullptr;
845 PointerRNA ptr_test; /* only support single level props */
846 if (RNA_path_resolve_property(ptr, identifier, &ptr_test, &prop_test) &&
847 (ptr_test.type == ptr->type) && (ptr_test.data == ptr->data))
848 {
849 return prop_test;
850 }
851 }
852 else {
853 /* most common case */
855 PointerRNA propptr;
856
857 if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr)) {
858 return static_cast<PropertyRNA *>(propptr.data);
859 }
860 }
861
862 return nullptr;
863}
864
865static const char *rna_property_type_identifier(PropertyType prop_type)
866{
867 switch (prop_type) {
868 case PROP_BOOLEAN:
869 return RNA_struct_identifier(&RNA_BoolProperty);
870 case PROP_INT:
871 return RNA_struct_identifier(&RNA_IntProperty);
872 case PROP_FLOAT:
873 return RNA_struct_identifier(&RNA_FloatProperty);
874 case PROP_STRING:
875 return RNA_struct_identifier(&RNA_StringProperty);
876 case PROP_ENUM:
877 return RNA_struct_identifier(&RNA_EnumProperty);
878 case PROP_POINTER:
879 return RNA_struct_identifier(&RNA_PointerProperty);
880 case PROP_COLLECTION:
881 return RNA_struct_identifier(&RNA_CollectionProperty);
882 default:
883 return RNA_struct_identifier(&RNA_Property);
884 }
885}
886
888 const char *name,
889 const PropertyType property_type_check)
890{
892 if (!prop) {
893 return nullptr;
894 }
895 const PropertyType prop_type = RNA_property_type(prop);
896 if (prop_type == property_type_check) {
897 return prop;
898 }
899 CLOG_WARN(&LOG,
900 "'%s : %s()' expected, got '%s : %s()'",
901 name,
902 rna_property_type_identifier(property_type_check),
903 name,
905 return nullptr;
906}
907
909 const char *name,
910 const StructRNA *struct_type_check)
911{
913 if (!prop) {
914 return nullptr;
915 }
916
917 const PropertyType prop_type = RNA_property_type(prop);
918 const StructRNA *prop_struct_type = RNA_property_pointer_type(&props, prop);
919 if (prop_type == PROP_COLLECTION && prop_struct_type == struct_type_check) {
920 return prop;
921 }
922
923 if (prop_type != PROP_COLLECTION) {
924 CLOG_WARN(&LOG,
925 "'%s : %s(type = %s)' expected, got '%s : %s()'",
926 name,
928 RNA_struct_identifier(struct_type_check),
929 name,
931 return nullptr;
932 }
933
934 CLOG_WARN(&LOG,
935 "'%s : %s(type = %s)' expected, got '%s : %s(type = %s)'.",
936 name,
938 RNA_struct_identifier(struct_type_check),
939 name,
941 RNA_struct_identifier(prop_struct_type));
942 return nullptr;
943}
944
946{
947 PropertyRNA *prop = nullptr;
948
949 RNA_STRUCT_BEGIN (ptr, iprop) {
950 /* This assumes that there can only be one user of this nested struct */
951 if (RNA_property_pointer_type(ptr, iprop) == srna) {
952 prop = iprop;
953 break;
954 }
955 }
957
958 return prop;
959}
960
962{
963 /* NOTE: prop_test could be freed memory, only use for comparison. */
964
965 /* validate the RNA is ok */
966 PropertyRNA *iterprop;
967 bool found = false;
968
969 iterprop = RNA_struct_iterator_property(ptr->type);
970
971 RNA_PROP_BEGIN (ptr, itemptr, iterprop) {
972 // PropertyRNA *prop = itemptr.data;
973 if (prop_test == (PropertyRNA *)itemptr.data) {
974 found = true;
975 break;
976 }
977 }
979
980 return found;
981}
982
984{
985 uint counter = 0;
986
987 PointerRNA struct_ptr = RNA_pointer_create_discrete(nullptr, srna, nullptr);
988
989 RNA_STRUCT_BEGIN (&struct_ptr, prop) {
990 counter++;
991 UNUSED_VARS(prop);
992 }
994
995 return counter;
996}
997
999 const StructRNA *srna)
1000{
1001 if (RNA_struct_is_a(ptr->type, srna)) {
1002 return {{ptr->type, ptr->data}};
1003 }
1004 else {
1005 for (int i = ptr->ancestors.size() - 1; i >= 0; i--) {
1006 const AncestorPointerRNA &ancestor = ptr->ancestors[i];
1007 if (RNA_struct_is_a(ancestor.type, srna)) {
1008 return ancestor;
1009 }
1010 }
1011 }
1012
1013 return std::nullopt;
1014}
1015
1017{
1018 return &srna->cont.properties;
1019}
1020
1022{
1023 return static_cast<PropertyRNA *>(
1024 BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier)));
1025}
1026
1028{
1029 for (; srna; srna = srna->base) {
1030 PropertyRNA *prop = RNA_struct_type_find_property_no_base(srna, identifier);
1031 if (prop != nullptr) {
1032 return prop;
1033 }
1034 }
1035 return nullptr;
1036}
1037
1038FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
1039{
1040#if 1
1041 FunctionRNA *func;
1042 for (; srna; srna = srna->base) {
1044 &srna->functions, identifier, offsetof(FunctionRNA, identifier));
1045 if (func) {
1046 return func;
1047 }
1048 }
1049 return nullptr;
1050
1051 /* functional but slow */
1052#else
1053 PropertyRNA *iterprop;
1054 FunctionRNA *func;
1055
1056 PointerRNA tptr = RNA_pointer_create_discrete(nullptr, &RNA_Struct, srna);
1057 iterprop = RNA_struct_find_property(&tptr, "functions");
1058
1059 func = nullptr;
1060
1061 RNA_PROP_BEGIN (&tptr, funcptr, iterprop) {
1062 if (STREQ(identifier, RNA_function_identifier(funcptr.data))) {
1063 func = funcptr.data;
1064 break;
1065 }
1066 }
1068
1069 return func;
1070#endif
1071}
1072
1074{
1075 return &srna->functions;
1076}
1077
1079{
1080 return type->reg;
1081}
1082
1084{
1085 do {
1086 if (type->unreg) {
1087 return type->unreg;
1088 }
1089 } while ((type = type->base));
1090
1091 return nullptr;
1092}
1093
1095{
1096 StructRNA *type = ptr->type;
1097
1098 do {
1099 if (type->instance) {
1100 return type->instance(ptr);
1101 }
1102 } while ((type = type->base));
1103
1104 return nullptr;
1105}
1106
1108{
1109 return srna->py_type;
1110}
1111
1112void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
1113{
1114 srna->py_type = py_type;
1115}
1116
1118{
1119 return srna->blender_type;
1120}
1121
1122void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
1123{
1124 srna->blender_type = blender_type;
1125}
1126
1128 PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len, PropertyRNA **r_nameprop)
1129{
1130 if (ptr->data) {
1131 if (PropertyRNA *nameprop = RNA_struct_name_property(ptr->type)) {
1132 *r_nameprop = nameprop;
1133 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
1134 }
1135 }
1136 return nullptr;
1137}
1138
1139char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
1140{
1141 if (ptr->data) {
1142 if (PropertyRNA *nameprop = RNA_struct_name_property(ptr->type)) {
1143 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
1144 }
1145 }
1146 return nullptr;
1147}
1148
1149bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
1150{
1151 const StructRNA *srna_exists = RNA_struct_find(identifier);
1152 if (UNLIKELY(srna_exists != nullptr)) {
1153 /* Use comprehensive string construction since this is such a rare occurrence
1154 * and information here may cut down time troubleshooting. */
1155 DynStr *dynstr = BLI_dynstr_new();
1156 BLI_dynstr_appendf(dynstr, "Type identifier '%s' is already in use: '", identifier);
1157 BLI_dynstr_append(dynstr, srna_exists->identifier);
1158 int i = 0;
1159 if (srna_exists->base) {
1160 for (const StructRNA *base = srna_exists->base; base; base = base->base) {
1161 BLI_dynstr_append(dynstr, "(");
1162 BLI_dynstr_append(dynstr, base->identifier);
1163 i += 1;
1164 }
1165 while (i--) {
1166 BLI_dynstr_append(dynstr, ")");
1167 }
1168 }
1169 BLI_dynstr_append(dynstr, "'.");
1170 char *result = BLI_dynstr_get_cstring(dynstr);
1171 BLI_dynstr_free(dynstr);
1172 BKE_report(reports, RPT_ERROR, result);
1174 return false;
1175 }
1176 return true;
1177}
1178
1180 const char *identifier,
1181 const char *sep)
1182{
1183 const int len_sep = strlen(sep);
1184 const int len_id = strlen(identifier);
1185 const char *p = strstr(identifier, sep);
1186 /* TODO: make error, for now warning until add-ons update. */
1187#if 1
1188 const int report_level = RPT_WARNING;
1189 const bool failure = true;
1190#else
1191 const int report_level = RPT_ERROR;
1192 const bool failure = false;
1193#endif
1194 if (p == nullptr || p == identifier || p + len_sep >= identifier + len_id) {
1195 BKE_reportf(reports,
1196 eReportType(report_level),
1197 "'%s' does not contain '%s' with prefix and suffix",
1198 identifier,
1199 sep);
1200 return failure;
1201 }
1202
1203 const char *c, *start, *end, *last;
1204 start = identifier;
1205 end = p;
1206 last = end - 1;
1207 for (c = start; c != end; c++) {
1208 if (((*c >= 'A' && *c <= 'Z') || ((c != start) && (*c >= '0' && *c <= '9')) ||
1209 ((c != start) && (c != last) && (*c == '_'))) == 0)
1210 {
1211 BKE_reportf(reports,
1212 eReportType(report_level),
1213 "'%s' does not have upper case alphanumeric prefix",
1214 identifier);
1215 return failure;
1216 }
1217 }
1218
1219 start = p + len_sep;
1220 end = identifier + len_id;
1221 last = end - 1;
1222 for (c = start; c != end; c++) {
1223 if (((*c >= 'A' && *c <= 'Z') || (*c >= 'a' && *c <= 'z') || (*c >= '0' && *c <= '9') ||
1224 ((c != start) && (c != last) && (*c == '_'))) == 0)
1225 {
1226 BKE_reportf(reports,
1227 eReportType(report_level),
1228 "'%s' does not have an alphanumeric suffix",
1229 identifier);
1230 return failure;
1231 }
1232 }
1233 return true;
1234}
1235
1236/* Property Information */
1237
1238const char *RNA_property_identifier(const PropertyRNA *prop)
1239{
1240 return rna_ensure_property_identifier(prop);
1241}
1242
1244{
1246}
1247
1249{
1250 return prop->deprecated;
1251}
1252
1257
1259{
1260 PropertyRNA *rna_prop = rna_ensure_property(prop);
1261
1262 /* For custom properties, find and parse the 'subtype' metadata field. */
1263 if (prop->magic != RNA_MAGIC) {
1264 IDProperty *idprop = (IDProperty *)prop;
1265
1266 if (idprop->type == IDP_STRING && idprop->subtype == IDP_STRING_SUB_BYTE) {
1267 return PROP_BYTESTRING;
1268 }
1269
1270 if (idprop->ui_data) {
1271 IDPropertyUIData *ui_data = idprop->ui_data;
1272 return (PropertySubType)ui_data->rna_subtype;
1273 }
1274 }
1275
1276 return rna_prop->subtype;
1277}
1278
1283
1285{
1286 PropertyRNA *rna_prop = rna_ensure_property(prop);
1287
1288 switch (rna_prop->type) {
1289 case PROP_INT: {
1290 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_prop;
1291 return iprop->ui_scale_type;
1292 }
1293 case PROP_FLOAT: {
1294 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_prop;
1295 return fprop->ui_scale_type;
1296 }
1297 default:
1298 return PROP_SCALE_LINEAR;
1299 }
1300}
1301
1303{
1304 return rna_ensure_property(prop)->flag;
1305}
1306
1308{
1309 return rna_ensure_property(prop)->tags;
1310}
1311
1316
1318{
1319 return (rna_ensure_property(prop)->flag_internal & PROP_INTERN_BUILTIN) != 0;
1320}
1321
1323{
1324 /* This is only called in isolated situations (mainly by the Python API),
1325 * so skip check for ID properties. Callers must use #RNA_property_is_idprop
1326 * when it's not known if the property might be an ID Property. */
1327 BLI_assert(prop->magic == RNA_MAGIC);
1328 return prop->py_data;
1329}
1330
1335
1340
1342{
1343 PropertyRNA *rprop = rna_ensure_property(prop);
1344
1345 if (length) {
1347 }
1348
1349 return rprop->arraydimension;
1350}
1351
1353{
1355
1357
1358 return len[dimension];
1359}
1360
1362{
1363 const char *vectoritem = "XYZW";
1364 const char *quatitem = "WXYZ";
1365 const char *coloritem = "RGBA";
1366 PropertySubType subtype = RNA_property_subtype(prop);
1367
1368 BLI_assert(index >= 0);
1369
1370 /* get string to use for array index */
1371 if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1372 return quatitem[index];
1373 }
1374 if ((index < 4) && ELEM(subtype,
1377 PROP_XYZ,
1379 PROP_EULER,
1382 PROP_COORDS))
1383 {
1384 return vectoritem[index];
1385 }
1386 if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1387 return coloritem[index];
1388 }
1389
1390 return '\0';
1391}
1392
1394{
1395 /* Don't use custom property sub-types in RNA path lookup. */
1397
1398 /* get index based on string name/alias */
1399 /* maybe a function to find char index in string would be better than all the switches */
1400 if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1401 switch (name) {
1402 case 'w':
1403 return 0;
1404 case 'x':
1405 return 1;
1406 case 'y':
1407 return 2;
1408 case 'z':
1409 return 3;
1410 }
1411 }
1412 else if (ELEM(subtype,
1415 PROP_XYZ,
1417 PROP_EULER,
1420 {
1421 switch (name) {
1422 case 'x':
1423 return 0;
1424 case 'y':
1425 return 1;
1426 case 'z':
1427 return 2;
1428 case 'w':
1429 return 3;
1430 }
1431 }
1432 else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1433 switch (name) {
1434 case 'r':
1435 return 0;
1436 case 'g':
1437 return 1;
1438 case 'b':
1439 return 2;
1440 case 'a':
1441 return 3;
1442 }
1443 }
1444
1445 return -1;
1446}
1447
1448void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
1449{
1451 int softmin, softmax;
1452
1453 if (prop->magic != RNA_MAGIC) {
1454 const IDProperty *idprop = (IDProperty *)prop;
1455 if (idprop->ui_data) {
1456 IDPropertyUIDataInt *ui_data = (IDPropertyUIDataInt *)idprop->ui_data;
1457 *hardmin = ui_data->min;
1458 *hardmax = ui_data->max;
1459 }
1460 else {
1461 *hardmin = INT_MIN;
1462 *hardmax = INT_MAX;
1463 }
1464 return;
1465 }
1466
1467 if (iprop->range) {
1468 *hardmin = INT_MIN;
1469 *hardmax = INT_MAX;
1470
1471 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1472 }
1473 else if (iprop->range_ex) {
1474 *hardmin = INT_MIN;
1475 *hardmax = INT_MAX;
1476
1477 iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1478 }
1479 else {
1480 *hardmin = iprop->hardmin;
1481 *hardmax = iprop->hardmax;
1482 }
1483}
1484
1486 PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
1487{
1489 int hardmin, hardmax;
1490
1491 if (prop->magic != RNA_MAGIC) {
1492 const IDProperty *idprop = (IDProperty *)prop;
1493 if (idprop->ui_data) {
1494 IDPropertyUIDataInt *ui_data_int = (IDPropertyUIDataInt *)idprop->ui_data;
1495 *softmin = ui_data_int->soft_min;
1496 *softmax = ui_data_int->soft_max;
1497 *step = ui_data_int->step;
1498 }
1499 else {
1500 *softmin = INT_MIN;
1501 *softmax = INT_MAX;
1502 *step = 1;
1503 }
1504 return;
1505 }
1506
1507 *softmin = iprop->softmin;
1508 *softmax = iprop->softmax;
1509
1510 if (iprop->range) {
1511 hardmin = INT_MIN;
1512 hardmax = INT_MAX;
1513
1514 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1515
1516 *softmin = max_ii(*softmin, hardmin);
1517 *softmax = min_ii(*softmax, hardmax);
1518 }
1519 else if (iprop->range_ex) {
1520 hardmin = INT_MIN;
1521 hardmax = INT_MAX;
1522
1523 iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1524
1525 *softmin = max_ii(*softmin, hardmin);
1526 *softmax = min_ii(*softmax, hardmax);
1527 }
1528
1529 *step = iprop->step;
1530}
1531
1532void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1533{
1535 float softmin, softmax;
1536
1537 if (prop->magic != RNA_MAGIC) {
1538 const IDProperty *idprop = (IDProperty *)prop;
1539 if (idprop->ui_data) {
1541 *hardmin = float(ui_data->min);
1542 *hardmax = float(ui_data->max);
1543 }
1544 else {
1545 *hardmin = -FLT_MAX;
1546 *hardmax = FLT_MAX;
1547 }
1548 return;
1549 }
1550
1551 if (fprop->range) {
1552 *hardmin = -FLT_MAX;
1553 *hardmax = FLT_MAX;
1554
1555 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1556 }
1557 else if (fprop->range_ex) {
1558 *hardmin = -FLT_MAX;
1559 *hardmax = FLT_MAX;
1560
1561 fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1562 }
1563 else {
1564 *hardmin = fprop->hardmin;
1565 *hardmax = fprop->hardmax;
1566 }
1567}
1568
1570 PropertyRNA *prop,
1571 float *softmin,
1572 float *softmax,
1573 float *step,
1574 float *precision)
1575{
1577 float hardmin, hardmax;
1578
1579 if (prop->magic != RNA_MAGIC) {
1580 const IDProperty *idprop = (IDProperty *)prop;
1581 if (idprop->ui_data) {
1583 *softmin = float(ui_data->soft_min);
1584 *softmax = float(ui_data->soft_max);
1585 *step = ui_data->step;
1586 *precision = float(ui_data->precision);
1587 }
1588 else {
1589 *softmin = -FLT_MAX;
1590 *softmax = FLT_MAX;
1591 *step = 1.0f;
1592 *precision = 3.0f;
1593 }
1594 return;
1595 }
1596
1597 *softmin = fprop->softmin;
1598 *softmax = fprop->softmax;
1599
1600 if (fprop->range) {
1601 hardmin = -FLT_MAX;
1602 hardmax = FLT_MAX;
1603
1604 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1605
1606 *softmin = max_ff(*softmin, hardmin);
1607 *softmax = min_ff(*softmax, hardmax);
1608 }
1609 else if (fprop->range_ex) {
1610 hardmin = -FLT_MAX;
1611 hardmax = FLT_MAX;
1612
1613 fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1614
1615 *softmin = max_ff(*softmin, hardmin);
1616 *softmax = min_ff(*softmax, hardmax);
1617 }
1618
1619 *step = fprop->step;
1620 *precision = float(fprop->precision);
1621}
1622
1624{
1625 float min, max;
1626
1628
1629 if (*value < min) {
1630 *value = min;
1631 return -1;
1632 }
1633 if (*value > max) {
1634 *value = max;
1635 return 1;
1636 }
1637 return 0;
1638}
1639
1641{
1642 int min, max;
1643
1644 RNA_property_int_range(ptr, prop, &min, &max);
1645
1646 if (*value < min) {
1647 *value = min;
1648 return -1;
1649 }
1650 if (*value > max) {
1651 *value = max;
1652 return 1;
1653 }
1654 return 0;
1655}
1656
1658{
1660 return sprop->maxlength;
1661}
1662
1664{
1665 if (prop->magic != RNA_MAGIC) {
1666 const IDProperty *idprop = (IDProperty *)prop;
1667 if (idprop->type == IDP_ID) {
1668 const IDPropertyUIDataID *ui_data = (const IDPropertyUIDataID *)idprop->ui_data;
1669 if (ui_data) {
1670 return ID_code_to_RNA_type(ui_data->id_type);
1671 }
1672 }
1673 }
1674
1675 prop = rna_ensure_property(prop);
1676
1677 if (prop->type == PROP_POINTER) {
1678 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1679
1680 if (pprop->type_fn) {
1681 return pprop->type_fn(ptr);
1682 }
1683 if (pprop->type) {
1684 return pprop->type;
1685 }
1686 }
1687 else if (prop->type == PROP_COLLECTION) {
1689
1690 if (cprop->item_type) {
1691 return cprop->item_type;
1692 }
1693 }
1694 /* ignore other types, rna_struct_find_nested calls with unchecked props */
1695
1696 return &RNA_UnknownType;
1697}
1698
1700{
1701 prop = rna_ensure_property(prop);
1702
1703 if (prop->type != PROP_POINTER) {
1704 printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
1705 return false;
1706 }
1707
1708 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1709
1710 /* Can't point from linked to local datablock. */
1711 if (ptr->owner_id && value->owner_id && !BKE_id_can_use_id(*ptr->owner_id, *value->owner_id)) {
1712 return false;
1713 }
1714
1715 /* Check custom poll function. */
1716 if (!pprop->poll) {
1717 return true;
1718 }
1719
1720 if (rna_idproperty_check(&prop, ptr)) {
1721 return reinterpret_cast<PropPointerPollFuncPy>(reinterpret_cast<void *>(pprop->poll))(
1722 ptr, *value, prop);
1723 }
1724 return pprop->poll(ptr, *value);
1725}
1726
1728 PointerRNA *ptr,
1729 PropertyRNA *prop,
1730 const bool use_static,
1731 const EnumPropertyItem **r_item,
1732 int *r_totitem,
1733 bool *r_free)
1734{
1735 if (!use_static && prop->magic != RNA_MAGIC) {
1736 const IDProperty *idprop = (IDProperty *)prop;
1737 if (idprop->type == IDP_INT) {
1738 IDPropertyUIDataInt *ui_data = reinterpret_cast<IDPropertyUIDataInt *>(idprop->ui_data);
1739
1740 int totitem = 0;
1741 EnumPropertyItem *result = nullptr;
1742 if (ui_data) {
1743 for (const IDPropertyUIDataEnumItem &idprop_item :
1744 blender::Span(ui_data->enum_items, ui_data->enum_items_num))
1745 {
1746 BLI_assert(idprop_item.identifier != nullptr);
1747 BLI_assert(idprop_item.name != nullptr);
1748 const EnumPropertyItem item = {idprop_item.value,
1749 idprop_item.identifier,
1750 idprop_item.icon,
1751 idprop_item.name,
1752 idprop_item.description ? idprop_item.description : ""};
1753 RNA_enum_item_add(&result, &totitem, &item);
1754 }
1755 }
1756
1757 RNA_enum_item_end(&result, &totitem);
1758 *r_item = result;
1759 if (r_totitem) {
1760 /* Exclude the terminator item. */
1761 *r_totitem = totitem - 1;
1762 }
1763 *r_free = true;
1764 return;
1765 }
1766 }
1767
1769
1770 *r_free = false;
1771
1772 if (!use_static && (eprop->item_fn != nullptr)) {
1773 const bool no_context = (prop->flag & PROP_ENUM_NO_CONTEXT) ||
1774 ((ptr->type->flag & STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID) &&
1775 (ptr->owner_id == nullptr));
1776 if (C != nullptr || no_context) {
1777 const EnumPropertyItem *item;
1778
1779 item = eprop->item_fn(no_context ? nullptr : C, ptr, prop, r_free);
1780
1781 /* any callbacks returning nullptr should be fixed */
1782 BLI_assert(item != nullptr);
1783
1784 if (r_totitem) {
1785 int tot;
1786 for (tot = 0; item[tot].identifier; tot++) {
1787 /* pass */
1788 }
1789 *r_totitem = tot;
1790 }
1791
1792 *r_item = item;
1793 return;
1794 }
1795 }
1796
1797 *r_item = eprop->item;
1798 if (r_totitem) {
1799 *r_totitem = eprop->totitem;
1800 }
1801}
1802
1804 PointerRNA *ptr,
1805 PropertyRNA *prop,
1806 const EnumPropertyItem **r_item,
1807 int *r_totitem,
1808 bool *r_free)
1809{
1810 RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free);
1811}
1812
1813#ifdef WITH_INTERNATIONAL
1814static void property_enum_translate(PropertyRNA *prop,
1815 EnumPropertyItem **r_item,
1816 const int *totitem,
1817 bool *r_free)
1818{
1820 int i;
1821
1822 /* NOTE: Only do those tests once, and then use BLT_pgettext. */
1823 bool do_iface = BLT_translate_iface();
1824 bool do_tooltip = BLT_translate_tooltips();
1825 EnumPropertyItem *nitem;
1826
1827 if (!(do_iface || do_tooltip)) {
1828 return;
1829 }
1830
1831 if (*r_free) {
1832 nitem = *r_item;
1833 }
1834 else {
1835 const EnumPropertyItem *item = *r_item;
1836 int tot;
1837
1838 if (totitem) {
1839 tot = *totitem;
1840 }
1841 else {
1842 /* count */
1843 for (tot = 0; item[tot].identifier; tot++) {
1844 /* pass */
1845 }
1846 }
1847
1848 nitem = MEM_malloc_arrayN<EnumPropertyItem>(size_t(tot) + 1, __func__);
1849 memcpy(nitem, item, sizeof(EnumPropertyItem) * (tot + 1));
1850
1851 *r_free = true;
1852 }
1853
1854 const char *translation_context = RNA_property_translation_context(prop);
1855
1856 for (i = 0; nitem[i].identifier; i++) {
1857 if (nitem[i].name && do_iface) {
1858 nitem[i].name = BLT_pgettext(translation_context, nitem[i].name);
1859 }
1860 if (nitem[i].description && do_tooltip) {
1861 nitem[i].description = BLT_pgettext(nullptr, nitem[i].description);
1862 }
1863 }
1864
1865 *r_item = nitem;
1866 }
1867}
1868#endif
1869
1871 PointerRNA *ptr,
1872 PropertyRNA *prop,
1873 const EnumPropertyItem **r_item,
1874 int *r_totitem,
1875 bool *r_free)
1876{
1877 RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
1878
1879#ifdef WITH_INTERNATIONAL
1880 /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory
1881 * so allow the exception (callers are creating new arrays in this case). */
1882 property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free);
1883#endif
1884}
1885
1887 PointerRNA *ptr,
1888 PropertyRNA *prop,
1889 const EnumPropertyItem **r_item,
1890 int *r_totitem,
1891 bool *r_free)
1892{
1894 size_t mem_size = sizeof(EnumPropertyItem) * (size_t(eprop->totitem) + 1);
1895 /* first return all items */
1896 EnumPropertyItem *item_array = MEM_malloc_arrayN<EnumPropertyItem>(size_t(eprop->totitem) + 1,
1897 "enum_gettext_all");
1898 *r_free = true;
1899 memcpy(item_array, eprop->item, mem_size);
1900
1901 if (r_totitem) {
1902 *r_totitem = eprop->totitem;
1903 }
1904
1905 if (eprop->item_fn != nullptr) {
1906 const bool no_context = (eprop->property.flag & PROP_ENUM_NO_CONTEXT) ||
1907 ((ptr->type->flag & STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID) &&
1908 (ptr->owner_id == nullptr));
1909 if (C != nullptr || no_context) {
1910 const EnumPropertyItem *item;
1911 int i;
1912 bool free = false;
1913
1914 item = eprop->item_fn(no_context ? nullptr : nullptr, ptr, prop, &free);
1915
1916 /* any callbacks returning nullptr should be fixed */
1917 BLI_assert(item != nullptr);
1918
1919 for (i = 0; i < eprop->totitem; i++) {
1920 bool exists = false;
1921 int i_fixed;
1922
1923 /* Items that do not exist on list are returned,
1924 * but have their names/identifiers null'ed out. */
1925 for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
1926 if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
1927 exists = true;
1928 break;
1929 }
1930 }
1931
1932 if (!exists) {
1933 item_array[i].name = nullptr;
1934 item_array[i].identifier = "";
1935 }
1936 }
1937
1938 if (free) {
1939 MEM_freeN(item);
1940 }
1941 }
1942 }
1943
1944#ifdef WITH_INTERNATIONAL
1945 property_enum_translate(prop, &item_array, r_totitem, r_free);
1946#endif
1947 *r_item = item_array;
1948}
1949
1951 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
1952{
1953 const EnumPropertyItem *item;
1954 bool free;
1955 bool found;
1956
1957 RNA_property_enum_items(C, ptr, prop, &item, nullptr, &free);
1958
1959 if (item) {
1960 const int i = RNA_enum_from_identifier(item, identifier);
1961 if (i != -1) {
1962 *r_value = item[i].value;
1963 found = true;
1964 }
1965 else {
1966 found = false;
1967 }
1968
1969 if (free) {
1970 MEM_freeN(item);
1971 }
1972 }
1973 else {
1974 found = false;
1975 }
1976 return found;
1977}
1978
1979bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
1980{
1981 const int i = RNA_enum_from_value(item, value);
1982 if (i != -1) {
1983 *r_identifier = item[i].identifier;
1984 return true;
1985 }
1986 return false;
1987}
1988
1990 const int value,
1991 const char **r_identifier)
1992{
1993 int index = 0;
1994 for (; item->identifier; item++) {
1995 if (item->identifier[0] && item->value & value) {
1996 r_identifier[index++] = item->identifier;
1997 }
1998 }
1999 r_identifier[index] = nullptr;
2000 return index;
2001}
2002
2003bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
2004{
2005 const int i = RNA_enum_from_value(item, value);
2006 if (i != -1) {
2007 *r_name = item[i].name;
2008 return true;
2009 }
2010 return false;
2011}
2012
2014 int value,
2015 const char *translation_context,
2016 const char **r_name)
2017{
2018 bool result;
2019
2020 result = RNA_enum_name(item, value, r_name);
2021
2022 if (result) {
2023 *r_name = BLT_translate_do_iface(translation_context, *r_name);
2024 }
2025
2026 return result;
2027};
2028
2030 const int value,
2031 const char **r_description)
2032{
2033 const int i = RNA_enum_from_value(item, value);
2034 if (i != -1) {
2035 *r_description = item[i].description;
2036 return true;
2037 }
2038 return false;
2039}
2040
2041int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
2042{
2043 int i = 0;
2044 for (; item->identifier; item++, i++) {
2045 if (item->identifier[0] && STREQ(item->identifier, identifier)) {
2046 return i;
2047 }
2048 }
2049 return -1;
2050}
2051
2053 const char *identifier,
2054 int *r_value)
2055{
2056 const int i = RNA_enum_from_identifier(item, identifier);
2057 if (i == -1) {
2058 return false;
2059 }
2060 *r_value = item[i].value;
2061 return true;
2062}
2063
2064int RNA_enum_from_name(const EnumPropertyItem *item, const char *name)
2065{
2066 int i = 0;
2067 for (; item->identifier; item++, i++) {
2068 if (item->identifier[0] && STREQ(item->name, name)) {
2069 return i;
2070 }
2071 }
2072 return -1;
2073}
2074
2075int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
2076{
2077 int i = 0;
2078 for (; item->identifier; item++, i++) {
2079 if (item->identifier[0] && item->value == value) {
2080 return i;
2081 }
2082 }
2083 return -1;
2084}
2085
2087{
2088 uint i = 0;
2089
2090 while (item->identifier) {
2091 item++;
2092 i++;
2093 }
2094
2095 return i;
2096}
2097
2099 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
2100{
2101 const EnumPropertyItem *item = nullptr;
2102 bool free;
2103
2104 RNA_property_enum_items(C, ptr, prop, &item, nullptr, &free);
2105 if (item) {
2106 bool result;
2107 result = RNA_enum_identifier(item, value, r_identifier);
2108 if (free) {
2109 MEM_freeN(item);
2110 }
2111 return result;
2112 }
2113 return false;
2114}
2115
2117 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
2118{
2119 const EnumPropertyItem *item = nullptr;
2120 bool free;
2121
2122 RNA_property_enum_items(C, ptr, prop, &item, nullptr, &free);
2123 if (item) {
2124 bool result;
2125 result = RNA_enum_name(item, value, r_name);
2126 if (free) {
2127 MEM_freeN(item);
2128 }
2129
2130 return result;
2131 }
2132 return false;
2133}
2134
2136 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
2137{
2138 bool result;
2139
2140 result = RNA_property_enum_name(C, ptr, prop, value, r_name);
2141
2142 if (result) {
2143 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
2145 }
2146 }
2147
2148 return result;
2149}
2150
2152 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
2153{
2154 const EnumPropertyItem *item = nullptr;
2155 bool free;
2156
2157 RNA_property_enum_items(C, ptr, prop, &item, nullptr, &free);
2158 if (item) {
2159 const int i = RNA_enum_from_value(item, value);
2160 bool result;
2161
2162 if (i != -1) {
2163 *r_item = item[i];
2164 result = true;
2165 }
2166 else {
2167 result = false;
2168 }
2169
2170 if (free) {
2171 MEM_freeN(item);
2172 }
2173
2174 return result;
2175 }
2176 return false;
2177}
2178
2180 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
2181{
2182 const bool result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
2183
2186 r_item->description = BLT_translate_do_tooltip(nullptr, r_item->description);
2187 }
2188
2189 return result;
2190}
2191
2193 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
2194{
2195 const EnumPropertyItem *item = nullptr;
2196 bool free;
2197
2198 RNA_property_enum_items(C, ptr, prop, &item, nullptr, &free);
2199 if (item) {
2200 int result;
2201 result = RNA_enum_bitflag_identifiers(item, value, r_identifier);
2202 if (free) {
2203 MEM_freeN(item);
2204 }
2205
2206 return result;
2207 }
2208 return 0;
2209}
2210
2211const char *RNA_property_ui_name(const PropertyRNA *prop, const PointerRNA *ptr)
2212{
2213 if (ptr && prop->magic == RNA_MAGIC && prop->ui_name_func) {
2214 if (const char *name = prop->ui_name_func(ptr, prop, true)) {
2215 return name;
2216 }
2217 }
2219}
2220
2221const char *RNA_property_ui_name_raw(const PropertyRNA *prop, const PointerRNA *ptr)
2222{
2223 if (ptr && prop->magic == RNA_MAGIC && prop->ui_name_func) {
2224 if (const char *name = prop->ui_name_func(ptr, prop, false)) {
2225 return name;
2226 }
2227 }
2228 return rna_ensure_property_name(prop);
2229}
2230
2232{
2234}
2235
2237{
2239}
2240
2242{
2244}
2245
2247{
2248 return rna_ensure_property((PropertyRNA *)prop)->icon;
2249}
2250
2252 PropertyRNA *prop_orig,
2253 const int index,
2254 const char **r_info)
2255{
2256 ID *id = ptr->owner_id;
2257
2258 PropertyRNA *prop = rna_ensure_property(prop_orig);
2259
2260 const char *info = "";
2261 const int flag = (prop->itemeditable != nullptr && index >= 0) ?
2262 prop->itemeditable(ptr, index) :
2263 (prop->editable != nullptr ? prop->editable(ptr, &info) : prop->flag);
2264 if (r_info != nullptr) {
2265 *r_info = info;
2266 }
2267
2268 /* Early return if the property itself is not editable. */
2269 if ((flag & PROP_EDITABLE) == 0) {
2270 return false;
2271 }
2272 /* Only considered registerable properties "internal"
2273 * because regular properties may not be editable and still be displayed. */
2274 if (flag & PROP_REGISTER) {
2275 if (r_info != nullptr && (*r_info)[0] == '\0') {
2276 *r_info = N_("This property is for internal use only and cannot be edited");
2277 }
2278 return false;
2279 }
2280
2281 /* If there is no owning ID, the property is editable at this point. */
2282 if (id == nullptr) {
2283 return true;
2284 }
2285
2286 /* Handle linked or liboverride ID cases. */
2287 const bool is_linked_prop_exception = (prop->flag & PROP_LIB_EXCEPTION) != 0;
2288 if (!ID_IS_EDITABLE(id)) {
2289 if (is_linked_prop_exception) {
2290 return true;
2291 }
2292 if (r_info != nullptr && (*r_info)[0] == '\0') {
2293 *r_info = N_("Cannot edit this property from a linked data-block");
2294 }
2295 return false;
2296 }
2297 if (ID_IS_OVERRIDE_LIBRARY(id)) {
2298 const bool is_liboverride_system = BKE_lib_override_library_is_system_defined(G_MAIN, id);
2299 if (!RNA_property_overridable_get(ptr, prop_orig)) {
2300 if (r_info != nullptr && (*r_info)[0] == '\0') {
2301 *r_info = N_("Cannot edit this property from an override data-block");
2302 }
2303 return false;
2304 }
2305 if (is_liboverride_system && !is_linked_prop_exception) {
2306 if (r_info != nullptr && (*r_info)[0] == '\0') {
2307 *r_info = N_("Cannot edit this property from a system override data-block");
2308 }
2309 return false;
2310 }
2311 }
2312
2313 /* At this point, property is owned by a local ID and therefore fully editable. */
2314 return true;
2315}
2316
2318{
2319 return prop->flag_internal & PROP_INTERN_RUNTIME;
2320}
2321
2323{
2324 return rna_property_editable_do(ptr, prop, -1, nullptr);
2325}
2326
2327bool RNA_property_editable_info(const PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
2328{
2329 return rna_property_editable_do(ptr, prop, -1, r_info);
2330}
2331
2333{
2334 int flag;
2335 const char *dummy_info;
2336
2337 prop = rna_ensure_property(prop);
2338 flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
2339 return (flag & PROP_EDITABLE) != 0;
2340}
2341
2342bool RNA_property_editable_index(const PointerRNA *ptr, PropertyRNA *prop, const int index)
2343{
2344 BLI_assert(index >= 0);
2345
2346 return rna_property_editable_do(ptr, prop, index, nullptr);
2347}
2348
2350{
2351 /* check that base ID-block can support animation data */
2352 if (!id_can_have_animdata(ptr->owner_id)) {
2353 return false;
2354 }
2355
2356 PropertyRNA *prop_ensured = rna_ensure_property(prop_orig);
2357
2358 if (!(prop_ensured->flag & PROP_ANIMATABLE)) {
2359 return false;
2360 }
2361
2362 return true;
2363}
2364
2366{
2367 /* check that base ID-block can support animation data */
2368 if (!RNA_property_animateable(ptr, prop_orig)) {
2369 return false;
2370 }
2371
2372 /* Linked or LibOverride Action IDs are not editable at the FCurve level. */
2373 if (ptr->owner_id) {
2374 AnimData *anim_data = BKE_animdata_from_id(ptr->owner_id);
2375 if (anim_data && anim_data->action &&
2376 (!ID_IS_EDITABLE(anim_data->action) || ID_IS_OVERRIDE_LIBRARY(anim_data->action)))
2377 {
2378 return false;
2379 }
2380 }
2381
2382 return rna_property_editable_do(ptr, prop_orig, -1, nullptr);
2383}
2384
2386{
2387 if (!RNA_property_anim_editable(ptr, prop)) {
2388 return false;
2389 }
2390
2391 /* LibOverrides can only get drivers if their animdata (if any) was created for the local
2392 * liboverride, and there is none in the linked reference.
2393 *
2394 * See also #rna_AnimaData_override_apply. */
2395 if (ptr->owner_id && ID_IS_OVERRIDE_LIBRARY(ptr->owner_id)) {
2397 nullptr, ptr->owner_id, nullptr, nullptr);
2398 AnimData *linked_reference_anim_data = BKE_animdata_from_id(liboverride->reference);
2399 if (linked_reference_anim_data) {
2400 return false;
2401 }
2402 }
2403
2404 return true;
2405}
2406
2408{
2409 int len = 1, index;
2410 bool driven, special;
2411
2412 if (!prop) {
2413 return false;
2414 }
2415
2416 if (RNA_property_array_check(prop)) {
2418 }
2419
2420 for (index = 0; index < len; index++) {
2421 if (BKE_fcurve_find_by_rna(ptr, prop, index, nullptr, nullptr, &driven, &special)) {
2422 return true;
2423 }
2424 }
2425
2426 return false;
2427}
2429{
2430 const std::optional<std::string> path = RNA_path_from_ID_to_property(ptr, prop);
2431 bool ret = false;
2432
2433 if (path) {
2434 PointerRNA ptr_test;
2435 PropertyRNA *prop_test;
2436
2437 PointerRNA id_ptr = RNA_id_pointer_create(ptr->owner_id);
2438 if (RNA_path_resolve(&id_ptr, path->c_str(), &ptr_test, &prop_test) == true) {
2439 ret = (prop == prop_test);
2440 }
2441 }
2442
2443 return ret;
2444}
2445
2447 bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2448{
2449 const bool is_rna = (prop->magic == RNA_MAGIC);
2450 prop = rna_ensure_property(prop);
2451
2452 if (is_rna) {
2453 if (prop->update) {
2454 /* ideally no context would be needed for update, but there's some
2455 * parts of the code that need it still, so we have this exception */
2456 if (prop->flag & PROP_CONTEXT_UPDATE) {
2457 if (C) {
2459 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
2460 }
2461 else {
2462 reinterpret_cast<ContextUpdateFunc>(reinterpret_cast<void *>(prop->update))(C, ptr);
2463 }
2464 }
2465 }
2466 else {
2467 prop->update(bmain, scene, ptr);
2468 }
2469 }
2470
2471#if 1
2472 /* TODO(@ideasman42): Should eventually be replaced entirely by message bus (below)
2473 * for now keep since copy-on-eval, bugs are hard to track when we have other missing updates.
2474 */
2475 if (prop->noteflag) {
2476 WM_main_add_notifier(prop->noteflag, ptr->owner_id);
2477 }
2478#endif
2479
2480 /* if C is nullptr, we're updating from animation.
2481 * avoid slow-down from f-curves by not publishing (for now). */
2482 if (C != nullptr) {
2483 wmMsgBus *mbus = CTX_wm_message_bus(C);
2484 /* we could add nullptr check, for now don't */
2485 WM_msg_publish_rna(mbus, ptr, prop);
2486 }
2487 if (ptr->owner_id != nullptr && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) {
2488 const short id_type = GS(ptr->owner_id->name);
2489 if (ID_TYPE_USE_COPY_ON_EVAL(id_type)) {
2490 if (prop->flag & PROP_DEG_SYNC_ONLY) {
2492 }
2493 else {
2495 }
2496 }
2497 }
2498 /* End message bus. */
2499 }
2500
2501 if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
2502
2503 /* Disclaimer: this logic is not applied consistently, causing some confusing behavior.
2504 *
2505 * - When animated (which skips update functions).
2506 * - When ID-properties are edited via Python (since RNA properties aren't used in this case).
2507 *
2508 * Adding updates will add a lot of overhead in the case of animation.
2509 * For Python it may cause unexpected slow-downs for developers using ID-properties
2510 * for data storage. Further, the root ID isn't available with nested data-structures.
2511 *
2512 * So editing custom properties only causes updates in the UI,
2513 * keep this exception because it happens to be useful for driving settings.
2514 * Python developers on the other hand will need to manually 'update_tag', see: #74000. */
2515 DEG_id_tag_update(ptr->owner_id,
2517
2518 /* When updating an ID pointer property, tag depsgraph for update. */
2521 }
2522
2524 if (ptr->owner_id) {
2526 }
2527 /* Not nice as well, but the only way to make sure material preview
2528 * is updated with custom nodes.
2529 */
2530 if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->owner_id != nullptr) &&
2531 (GS(ptr->owner_id->name) == ID_NT))
2532 {
2534 }
2535 }
2536}
2537
2539{
2540 /* NOTE: must keep in sync with #rna_property_update. */
2541 return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
2542}
2543
2548
2550{
2551 BLI_assert(bmain != nullptr);
2552 rna_property_update(nullptr, bmain, scene, ptr, prop);
2553}
2554
2555/* ---------------------------------------------------------------------- */
2556
2557/* Property Data */
2558
2560{
2561 if (prop_rna_or_id.idprop) {
2562#ifdef USE_INT_IDPROPS_FOR_BOOLEAN_RNA_PROP
2563 return IDP_int_or_bool_get(prop_rna_or_id.idprop);
2564#else
2565 return IDP_bool_get(prop_rna_or_id.idprop);
2566#endif
2567 }
2568 BoolPropertyRNA *bprop = reinterpret_cast<BoolPropertyRNA *>(prop_rna_or_id.rnaprop);
2569 if (bprop->get) {
2570 return bprop->get(ptr);
2571 }
2572 if (bprop->get_ex) {
2573 return bprop->get_ex(ptr, &bprop->property);
2574 }
2575 return bprop->defaultvalue;
2576}
2577
2579{
2581
2582 PropertyRNAOrID prop_rna_or_id;
2583 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
2584 BLI_assert(!prop_rna_or_id.is_array);
2585 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
2586 prop = nullptr;
2587 BoolPropertyRNA *bprop = reinterpret_cast<BoolPropertyRNA *>(prop_rna_or_id.rnaprop);
2588
2589 bool value = property_boolean_get(ptr, prop_rna_or_id);
2590 if (bprop->get_transform) {
2591 value = bprop->get_transform(ptr, &bprop->property, value, prop_rna_or_id.is_set);
2592 }
2593
2594 return value;
2595}
2596
2598{
2600
2601 PropertyRNAOrID prop_rna_or_id;
2602 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
2603 BLI_assert(!prop_rna_or_id.is_array);
2604 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
2605 prop = nullptr;
2606 IDProperty *idprop = prop_rna_or_id.idprop;
2607 BoolPropertyRNA *bprop = reinterpret_cast<BoolPropertyRNA *>(prop_rna_or_id.rnaprop);
2608
2609 if (bprop->set_transform) {
2610 /* Get raw, untransformed (aka 'storage') value. */
2611 const bool curr_value = property_boolean_get(ptr, prop_rna_or_id);
2612 value = bprop->set_transform(ptr, &bprop->property, value, curr_value, prop_rna_or_id.is_set);
2613 }
2614
2615 if (idprop) {
2616#ifdef USE_INT_IDPROPS_FOR_BOOLEAN_RNA_PROP
2617 IDP_int_or_bool_set(idprop, value);
2618#else
2619 IDP_bool_set(idprop, value);
2620#endif
2621 rna_idproperty_touch(idprop);
2622 }
2623 else if (bprop->set) {
2624 bprop->set(ptr, value);
2625 }
2626 else if (bprop->set_ex) {
2627 bprop->set_ex(ptr, &bprop->property, value);
2628 }
2629 else if (bprop->property.flag & PROP_EDITABLE) {
2630 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
2631#ifdef USE_INT_IDPROPS_FOR_BOOLEAN_RNA_PROP
2633 group,
2635 .release());
2636#else
2638 group,
2640 .release());
2641#endif
2642 }
2643 }
2644}
2645
2647 const bool *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values)
2648{
2649 if (defarr && defarr_length > 0) {
2650 defarr_length = std::min(defarr_length, out_length);
2651 memcpy(r_values, defarr, sizeof(bool) * defarr_length);
2652 }
2653 else {
2654 defarr_length = 0;
2655 }
2656
2657 for (int i = defarr_length; i < out_length; i++) {
2658 r_values[i] = defvalue;
2659 }
2660}
2661
2663 const int *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values)
2664{
2665 if (defarr && defarr_length > 0) {
2666 defarr_length = std::min(defarr_length, out_length);
2667 for (int i = 0; i < defarr_length; i++) {
2668 r_values[i] = defarr[i] != 0;
2669 }
2670 }
2671 else {
2672 defarr_length = 0;
2673 }
2674
2675 for (int i = defarr_length; i < out_length; i++) {
2676 r_values[i] = defvalue;
2677 }
2678}
2679
2681 BoolPropertyRNA *bprop,
2682 bool *r_values)
2683{
2684 if (ptr->data && bprop->get_default_array) {
2685 bprop->get_default_array(ptr, &bprop->property, r_values);
2686 return;
2687 }
2688
2689 int length = bprop->property.totarraylength;
2690 int out_length = RNA_property_array_length(ptr, (PropertyRNA *)bprop);
2691
2693 bprop->defaultarray, length, bprop->defaultvalue, out_length, r_values);
2694}
2695
2697 PropertyRNAOrID &prop_rna_or_id,
2699{
2700 PropertyRNA *rna_prop = prop_rna_or_id.rnaprop;
2701 BoolPropertyRNA *bprop = reinterpret_cast<BoolPropertyRNA *>(rna_prop);
2702 if (prop_rna_or_id.idprop) {
2703 IDProperty *idprop = prop_rna_or_id.idprop;
2704 BLI_assert(idprop->len == RNA_property_array_length(ptr, rna_prop) ||
2705 (rna_prop->flag & PROP_IDPROPERTY));
2706 if (rna_prop->arraydimension == 0) {
2707 r_values[0] = RNA_property_boolean_get(ptr, rna_prop);
2708 }
2709 else if (idprop->subtype == IDP_INT) {
2710 /* Some boolean IDProperty arrays might be saved in files as an integer
2711 * array property, since the boolean IDProperty type was added later. */
2712 const int *values_src = IDP_array_int_get(idprop);
2713 for (int i = 0; i < idprop->len; i++) {
2714 r_values[i] = bool(values_src[i]);
2715 }
2716 }
2717 else if (idprop->subtype == IDP_BOOLEAN) {
2718 int8_t *values_src = IDP_array_bool_get(idprop);
2719 for (int i = 0; i < idprop->len; i++) {
2720 r_values[i] = values_src[i];
2721 }
2722 }
2723 }
2724 else if (rna_prop->arraydimension == 0) {
2725 r_values[0] = RNA_property_boolean_get(ptr, rna_prop);
2726 }
2727 else if (bprop->getarray) {
2728 bprop->getarray(ptr, r_values.data());
2729 }
2730 else if (bprop->getarray_ex) {
2731 bprop->getarray_ex(ptr, rna_prop, r_values.data());
2732 }
2733 else {
2735 }
2736}
2737
2739{
2741
2742 PropertyRNAOrID prop_rna_or_id;
2743 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
2744 BLI_assert(prop_rna_or_id.is_array);
2745 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
2746 prop = nullptr;
2747 BoolPropertyRNA *bprop = reinterpret_cast<BoolPropertyRNA *>(prop_rna_or_id.rnaprop);
2748
2749 blender::MutableSpan<bool> r_values(values, int64_t(prop_rna_or_id.array_len));
2750 values = nullptr; /* Do not access this 'raw' pointer anymore in code below. */
2751 property_boolean_get_array(ptr, prop_rna_or_id, r_values);
2752 if (bprop->getarray_transform) {
2753 /* NOTE: Given current implementation, it would _probably_ be safe to use `values` for both
2754 * input 'current values' and output 'final values', since python will make a copy of the input
2755 * anyways. Think it's better to keep it clean and make a copy here to avoid any potential
2756 * issues in the future though. */
2757 blender::Array<bool, RNA_STACK_ARRAY> curr_values(r_values.as_span());
2758 bprop->getarray_transform(
2759 ptr, &bprop->property, curr_values.data(), prop_rna_or_id.is_set, r_values.data());
2760 }
2761}
2762
2764 PropertyRNA *prop,
2765 bool *values,
2766 int values_num)
2767{
2768 BLI_assert(values_num >= 0);
2769 const int array_num = RNA_property_array_length(ptr, prop);
2770 if (values_num >= array_num) {
2771 RNA_property_boolean_get_array(ptr, prop, values);
2772 return;
2773 }
2774
2775 blender::Array<bool, RNA_STACK_ARRAY> value_buf(array_num);
2776 RNA_property_boolean_get_array(ptr, prop, value_buf.data());
2777 memcpy(values, value_buf.data(), sizeof(*values) * values_num);
2778}
2779
2781{
2782 bool tmp[RNA_MAX_ARRAY_LENGTH];
2784 bool value;
2785
2787 BLI_assert(RNA_property_array_check(prop) != false);
2788 BLI_assert(index >= 0);
2789 BLI_assert(index < len);
2790
2791 if (len <= RNA_MAX_ARRAY_LENGTH) {
2793 value = tmp[index];
2794 }
2795 else {
2796 bool *tmparray;
2797
2798 tmparray = MEM_malloc_arrayN<bool>(size_t(len), __func__);
2799 RNA_property_boolean_get_array(ptr, prop, tmparray);
2800 value = tmparray[index];
2801 MEM_freeN(tmparray);
2802 }
2803
2804 BLI_assert(ELEM(value, false, true));
2805
2806 return value;
2807}
2808
2810{
2812
2813 PropertyRNAOrID prop_rna_or_id;
2814 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
2815 BLI_assert(prop_rna_or_id.is_array);
2816 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
2817 prop = nullptr;
2818 IDProperty *idprop = prop_rna_or_id.idprop;
2819 PropertyRNA *rna_prop = prop_rna_or_id.rnaprop;
2820 BoolPropertyRNA *bprop = reinterpret_cast<BoolPropertyRNA *>(rna_prop);
2821
2822 const int64_t values_num = int64_t(prop_rna_or_id.array_len);
2823 blender::Span<bool> final_values(values, values_num);
2824 values = nullptr; /* Do not access this 'raw' pointer anymore in code below. */
2825 /* Default init does not allocate anything, so it's cheap. This is only reinitialized with actual
2826 * `values_num` items if `setarray_transform` is called. */
2827 blender::Array<bool, RNA_STACK_ARRAY> final_values_storage{};
2828 if (bprop->setarray_transform) {
2829 /* Get raw, untransformed (aka 'storage') value. */
2830 blender::Array<bool, RNA_STACK_ARRAY> curr_values(values_num);
2831 property_boolean_get_array(ptr, prop_rna_or_id, curr_values.as_mutable_span());
2832
2833 final_values_storage.reinitialize(values_num);
2834 bprop->setarray_transform(ptr,
2835 rna_prop,
2836 final_values.data(),
2837 curr_values.data(),
2838 prop_rna_or_id.is_set,
2839 final_values_storage.data());
2840 final_values = final_values_storage.as_span();
2841 }
2842
2843 if (idprop) {
2844 /* Support writing to integer and boolean IDProperties, since boolean
2845 * RNA properties used to be stored with integer IDProperties. */
2846 if (rna_prop->arraydimension == 0) {
2847 if (idprop->subtype == IDP_BOOLEAN) {
2848 IDP_bool_set(idprop, final_values[0]);
2849 }
2850 else {
2851 BLI_assert(idprop->subtype == IDP_INT);
2852 IDP_int_set(idprop, final_values[0]);
2853 }
2854 }
2855 else {
2856 BLI_assert(idprop->type = IDP_ARRAY);
2857 BLI_assert(idprop->len == values_num);
2858 if (idprop->subtype == IDP_BOOLEAN) {
2859 memcpy(IDP_array_bool_get(idprop),
2860 final_values.data(),
2861 sizeof(decltype(final_values)::value_type) * idprop->len);
2862 }
2863 else {
2864 BLI_assert(idprop->subtype == IDP_INT);
2865 int *values_dst = IDP_array_int_get(idprop);
2866 for (int i = 0; i < idprop->len; i++) {
2867 values_dst[i] = int(final_values[i]);
2868 }
2869 }
2870 }
2871 rna_idproperty_touch(idprop);
2872 }
2873 else if (rna_prop->arraydimension == 0) {
2874 RNA_property_boolean_set(ptr, rna_prop, final_values[0]);
2875 }
2876 else if (bprop->setarray) {
2877 bprop->setarray(ptr, final_values.data());
2878 }
2879 else if (bprop->setarray_ex) {
2880 bprop->setarray_ex(ptr, rna_prop, final_values.data());
2881 }
2882 else if (rna_prop->flag & PROP_EDITABLE) {
2883 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
2884 IDPropertyTemplate val = {0};
2885 val.array.len = rna_prop->totarraylength;
2886#ifdef USE_INT_IDPROPS_FOR_BOOLEAN_RNA_PROP
2887 val.array.type = IDP_INT;
2888#else
2889 val.array.type = IDP_BOOLEAN;
2890#endif
2891
2892 idprop = IDP_New(IDP_ARRAY, &val, prop_rna_or_id.identifier, IDP_FLAG_STATIC_TYPE);
2893 IDP_AddToGroup(group, idprop);
2894#ifdef USE_INT_IDPROPS_FOR_BOOLEAN_RNA_PROP
2895 int *values_dst = IDP_array_int_get(idprop);
2896 for (int i = 0; i < idprop->len; i++) {
2897 values_dst[i] = int(final_values[i]);
2898 }
2899#else
2900 int8_t *values_dst = IDP_array_bool_get(idprop);
2901 for (int i = 0; i < idprop->len; i++) {
2902 values_dst[i] = final_values[i];
2903 }
2904#endif
2905 }
2906 }
2907}
2908
2910 PropertyRNA *prop,
2911 const bool *values,
2912 int values_num)
2913{
2914 BLI_assert(values_num >= 0);
2915 const int array_num = RNA_property_array_length(ptr, prop);
2916 if (values_num >= array_num) {
2917 RNA_property_boolean_set_array(ptr, prop, values);
2918 return;
2919 }
2920
2921 blender::Array<bool, RNA_STACK_ARRAY> value_buf(array_num);
2922 RNA_property_boolean_get_array(ptr, prop, value_buf.data());
2923 memcpy(value_buf.data(), values, sizeof(*values) * values_num);
2924 RNA_property_boolean_set_array(ptr, prop, value_buf.data());
2925}
2926
2927void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
2928{
2929 bool tmp[RNA_MAX_ARRAY_LENGTH];
2931
2933 BLI_assert(RNA_property_array_check(prop) != false);
2934 BLI_assert(index >= 0);
2935 BLI_assert(index < len);
2936 BLI_assert(ELEM(value, false, true));
2937
2938 if (len <= RNA_MAX_ARRAY_LENGTH) {
2940 tmp[index] = value;
2942 }
2943 else {
2944 bool *tmparray;
2945
2946 tmparray = MEM_malloc_arrayN<bool>(size_t(len), __func__);
2947 RNA_property_boolean_get_array(ptr, prop, tmparray);
2948 tmparray[index] = value;
2949 RNA_property_boolean_set_array(ptr, prop, tmparray);
2950 MEM_freeN(tmparray);
2951 }
2952}
2953
2955{
2956 /* TODO: Make defaults work for IDProperties. */
2958
2960 BLI_assert(RNA_property_array_check(prop) == false);
2961 BLI_assert(ELEM(bprop->defaultvalue, false, true));
2962
2963 if (prop->magic != RNA_MAGIC) {
2964 const IDProperty *idprop = (const IDProperty *)prop;
2965 if (idprop->ui_data) {
2966 switch (IDP_ui_data_type(idprop)) {
2968 const IDPropertyUIDataBool *ui_data = (const IDPropertyUIDataBool *)idprop->ui_data;
2969 return ui_data->default_value;
2970 }
2971 case IDP_UI_DATA_TYPE_INT: {
2972 const IDPropertyUIDataInt *ui_data = (const IDPropertyUIDataInt *)idprop->ui_data;
2973 return ui_data->default_value != 0;
2974 }
2975 default:
2977 }
2978 }
2979 return false;
2980 }
2981 if (bprop->get_default) {
2982 return bprop->get_default(ptr, prop);
2983 }
2984
2985 return bprop->defaultvalue;
2986}
2987
2989{
2991
2993 BLI_assert(RNA_property_array_check(prop) != false);
2994
2995 if (prop->magic != RNA_MAGIC) {
2996 const IDProperty *idprop = (const IDProperty *)prop;
2997 if (idprop->ui_data) {
2998 BLI_assert(idprop->type == IDP_ARRAY);
2999 switch (IDP_ui_data_type(idprop)) {
3001 const IDPropertyUIDataBool *ui_data = (const IDPropertyUIDataBool *)idprop->ui_data;
3002 if (ui_data->default_array) {
3004 ui_data->default_array_len,
3005 ui_data->default_value,
3006 idprop->len,
3007 values);
3008 }
3009 else {
3011 nullptr, 0, ui_data->default_value, idprop->len, values);
3012 }
3013 break;
3014 }
3015 case IDP_UI_DATA_TYPE_INT: {
3016 const IDPropertyUIDataInt *ui_data = (const IDPropertyUIDataInt *)idprop->ui_data;
3017 if (ui_data->default_array) {
3019 ui_data->default_array_len,
3020 ui_data->default_value,
3021 idprop->len,
3022 values);
3023 }
3024 else {
3026 nullptr, 0, ui_data->default_value, idprop->len, values);
3027 }
3028 break;
3029 }
3030 default:
3032 break;
3033 }
3034 }
3035 }
3036 else if (prop->arraydimension == 0) {
3037 values[0] = bprop->defaultvalue;
3038 }
3039 else {
3041 }
3042}
3043
3045{
3046 bool tmp[RNA_MAX_ARRAY_LENGTH];
3048
3050 BLI_assert(RNA_property_array_check(prop) != false);
3051 BLI_assert(index >= 0);
3052 BLI_assert(index < len);
3053
3054 if (len <= RNA_MAX_ARRAY_LENGTH) {
3056 return tmp[index];
3057 }
3058 bool *tmparray, value;
3059
3060 tmparray = MEM_malloc_arrayN<bool>(size_t(len), __func__);
3062 value = tmparray[index];
3063 MEM_freeN(tmparray);
3064
3065 return value;
3066}
3067
3068static int property_int_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
3069{
3070 if (prop_rna_or_id.idprop) {
3071 return IDP_int_get(prop_rna_or_id.idprop);
3072 }
3073 IntPropertyRNA *iprop = reinterpret_cast<IntPropertyRNA *>(prop_rna_or_id.rnaprop);
3074 if (iprop->get) {
3075 return iprop->get(ptr);
3076 }
3077 if (iprop->get_ex) {
3078 return iprop->get_ex(ptr, &iprop->property);
3079 }
3080 return iprop->defaultvalue;
3081}
3082
3084{
3086
3087 PropertyRNAOrID prop_rna_or_id;
3088 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3089 BLI_assert(!prop_rna_or_id.is_array);
3090 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3091 prop = nullptr;
3092 IntPropertyRNA *iprop = reinterpret_cast<IntPropertyRNA *>(prop_rna_or_id.rnaprop);
3093
3094 int value = property_int_get(ptr, prop_rna_or_id);
3095 if (iprop->get_transform) {
3096 value = iprop->get_transform(ptr, &iprop->property, value, prop_rna_or_id.is_set);
3097 }
3098
3099 return value;
3100}
3101
3103{
3105
3106 PropertyRNAOrID prop_rna_or_id;
3107 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3108 BLI_assert(!prop_rna_or_id.is_array);
3109 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3110 prop = nullptr;
3111 IDProperty *idprop = prop_rna_or_id.idprop;
3112 IntPropertyRNA *iprop = reinterpret_cast<IntPropertyRNA *>(prop_rna_or_id.rnaprop);
3113
3114 if (iprop->set_transform) {
3115 /* Get raw, untransformed (aka 'storage') value. */
3116 const int curr_value = property_int_get(ptr, prop_rna_or_id);
3117 value = iprop->set_transform(ptr, &iprop->property, value, curr_value, prop_rna_or_id.is_set);
3118 }
3119
3120 if (idprop) {
3121 RNA_property_int_clamp(ptr, &iprop->property, &value);
3122 IDP_int_set(idprop, value);
3123 rna_idproperty_touch(idprop);
3124 }
3125 else if (iprop->set) {
3126 iprop->set(ptr, value);
3127 }
3128 else if (iprop->set_ex) {
3129 iprop->set_ex(ptr, &iprop->property, value);
3130 }
3131 else if (iprop->property.flag & PROP_EDITABLE) {
3132 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
3133 RNA_property_int_clamp(ptr, &iprop->property, &value);
3135 group,
3137 .release());
3138 }
3139 }
3140}
3141
3143 const int *defarr, int defarr_length, int defvalue, int out_length, int *r_values)
3144{
3145 if (defarr && defarr_length > 0) {
3146 defarr_length = std::min(defarr_length, out_length);
3147 memcpy(r_values, defarr, sizeof(int) * defarr_length);
3148 }
3149 else {
3150 defarr_length = 0;
3151 }
3152
3153 for (int i = defarr_length; i < out_length; i++) {
3154 r_values[i] = defvalue;
3155 }
3156}
3157
3159 IntPropertyRNA *iprop,
3160 int *r_values)
3161{
3162 if (ptr->data && iprop->get_default_array) {
3163 iprop->get_default_array(ptr, &iprop->property, r_values);
3164 return;
3165 }
3166
3167 int length = iprop->property.totarraylength;
3168 int out_length = RNA_property_array_length(ptr, (PropertyRNA *)iprop);
3169
3171 iprop->defaultarray, length, iprop->defaultvalue, out_length, r_values);
3172}
3173
3175 PropertyRNAOrID &prop_rna_or_id,
3177{
3178 PropertyRNA *rna_prop = prop_rna_or_id.rnaprop;
3179 IntPropertyRNA *iprop = reinterpret_cast<IntPropertyRNA *>(rna_prop);
3180 if (prop_rna_or_id.idprop) {
3181 IDProperty *idprop = prop_rna_or_id.idprop;
3182 BLI_assert(idprop->len == RNA_property_array_length(ptr, rna_prop) ||
3183 (rna_prop->flag & PROP_IDPROPERTY));
3184 if (rna_prop->arraydimension == 0) {
3185 r_values[0] = RNA_property_int_get(ptr, rna_prop);
3186 }
3187 else {
3188 memcpy(r_values.data(),
3189 IDP_array_int_get(idprop),
3190 sizeof(decltype(r_values)::value_type) * idprop->len);
3191 }
3192 }
3193 else if (rna_prop->arraydimension == 0) {
3194 r_values[0] = RNA_property_int_get(ptr, rna_prop);
3195 }
3196 else if (iprop->getarray) {
3197 iprop->getarray(ptr, r_values.data());
3198 }
3199 else if (iprop->getarray_ex) {
3200 iprop->getarray_ex(ptr, rna_prop, r_values.data());
3201 }
3202 else {
3204 }
3205}
3206
3208{
3210
3211 PropertyRNAOrID prop_rna_or_id;
3212 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3213 BLI_assert(prop_rna_or_id.is_array);
3214 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3215 prop = nullptr;
3216 IntPropertyRNA *iprop = reinterpret_cast<IntPropertyRNA *>(prop_rna_or_id.rnaprop);
3217
3218 blender::MutableSpan<int> r_values(values, int64_t(prop_rna_or_id.array_len));
3219 values = nullptr; /* Do not access this 'raw' pointer anymore in code below. */
3220 property_int_get_array(ptr, prop_rna_or_id, r_values);
3221 if (iprop->getarray_transform) {
3222 /* NOTE: Given current implementation, it would _probably_ be safe to use `values` for both
3223 * input 'current values' and output 'final values', since python will make a copy of the input
3224 * anyways. Think it's better to keep it clean and make a copy here to avoid any potential
3225 * issues in the future though. */
3226 blender::Array<int, RNA_STACK_ARRAY> curr_values(r_values.as_span());
3227 iprop->getarray_transform(
3228 ptr, &iprop->property, curr_values.data(), prop_rna_or_id.is_set, r_values.data());
3229 }
3230}
3231
3233 PropertyRNA *prop,
3234 int *values,
3235 int values_num)
3236{
3237 BLI_assert(values_num >= 0);
3238 const int array_num = RNA_property_array_length(ptr, prop);
3239 if (values_num >= array_num) {
3240 RNA_property_int_get_array(ptr, prop, values);
3241 return;
3242 }
3243
3244 blender::Array<int, RNA_STACK_ARRAY> value_buf(array_num);
3245 RNA_property_int_get_array(ptr, prop, value_buf.data());
3246 memcpy(values, value_buf.data(), sizeof(*values) * values_num);
3247}
3248
3250{
3251 const int array_len = RNA_property_array_length(ptr, prop);
3252
3253 if (array_len <= 0) {
3254 values[0] = 0;
3255 values[1] = 0;
3256 }
3257 else if (array_len == 1) {
3258 RNA_property_int_get_array(ptr, prop, values);
3259 values[1] = values[0];
3260 }
3261 else {
3262 int arr_stack[32];
3263 int *arr;
3264 int i;
3265
3266 if (array_len > 32) {
3267 arr = MEM_malloc_arrayN<int>(size_t(array_len), __func__);
3268 }
3269 else {
3270 arr = arr_stack;
3271 }
3272
3273 RNA_property_int_get_array(ptr, prop, arr);
3274 values[0] = values[1] = arr[0];
3275 for (i = 1; i < array_len; i++) {
3276 values[0] = std::min(values[0], arr[i]);
3277 values[1] = std::max(values[1], arr[i]);
3278 }
3279
3280 if (arr != arr_stack) {
3281 MEM_freeN(arr);
3282 }
3283 }
3284}
3285
3287{
3288 int tmp[RNA_MAX_ARRAY_LENGTH];
3290
3292 BLI_assert(RNA_property_array_check(prop) != false);
3293 BLI_assert(index >= 0);
3294 BLI_assert(index < len);
3295
3296 if (len <= RNA_MAX_ARRAY_LENGTH) {
3297 RNA_property_int_get_array(ptr, prop, tmp);
3298 return tmp[index];
3299 }
3300 int *tmparray, value;
3301
3302 tmparray = MEM_malloc_arrayN<int>(size_t(len), __func__);
3303 RNA_property_int_get_array(ptr, prop, tmparray);
3304 value = tmparray[index];
3305 MEM_freeN(tmparray);
3306
3307 return value;
3308}
3309
3311{
3313
3314 PropertyRNAOrID prop_rna_or_id;
3315 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3316 BLI_assert(prop_rna_or_id.is_array);
3317 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3318 prop = nullptr;
3319 IDProperty *idprop = prop_rna_or_id.idprop;
3320 PropertyRNA *rna_prop = prop_rna_or_id.rnaprop;
3321 IntPropertyRNA *iprop = reinterpret_cast<IntPropertyRNA *>(rna_prop);
3322
3323 const int64_t values_num = int64_t(prop_rna_or_id.array_len);
3324 blender::Span<int> final_values(values, values_num);
3325 values = nullptr; /* Do not access this 'raw' pointer anymore in code below. */
3326 /* Default init does not allocate anything, so it's cheap. This is only reinitialized with actual
3327 * `values_num` items if `setarray_transform` is called. */
3328 blender::Array<int, RNA_STACK_ARRAY> final_values_storage{};
3329 if (iprop->setarray_transform) {
3330 /* Get raw, untransformed (aka 'storage') value. */
3331 blender::Array<int, RNA_STACK_ARRAY> curr_values(values_num);
3332 property_int_get_array(ptr, prop_rna_or_id, curr_values.as_mutable_span());
3333
3334 final_values_storage.reinitialize(values_num);
3335 iprop->setarray_transform(ptr,
3336 rna_prop,
3337 final_values.data(),
3338 curr_values.data(),
3339 prop_rna_or_id.is_set,
3340 final_values_storage.data());
3341 final_values = final_values_storage.as_span();
3342 }
3343
3344 if (idprop) {
3345 BLI_assert(idprop->len == values_num);
3346 if (rna_prop->arraydimension == 0) {
3347 IDP_int_set(idprop, final_values[0]);
3348 }
3349 else {
3350 memcpy(IDP_array_int_get(idprop),
3351 final_values.data(),
3352 sizeof(decltype(final_values)::value_type) * idprop->len);
3353 }
3354
3355 rna_idproperty_touch(idprop);
3356 }
3357 else if (rna_prop->arraydimension == 0) {
3358 RNA_property_int_set(ptr, rna_prop, final_values[0]);
3359 }
3360 else if (iprop->setarray) {
3361 iprop->setarray(ptr, final_values.data());
3362 }
3363 else if (iprop->setarray_ex) {
3364 iprop->setarray_ex(ptr, rna_prop, final_values.data());
3365 }
3366 else if (rna_prop->flag & PROP_EDITABLE) {
3367 // RNA_property_int_clamp_array(ptr, prop, &value); /* TODO. */
3368 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
3369 IDP_AddToGroup(group,
3371 prop_rna_or_id.identifier, final_values, IDP_FLAG_STATIC_TYPE)
3372 .release());
3373 }
3374 }
3375}
3376
3378 PropertyRNA *prop,
3379 const int *values,
3380 int values_num)
3381{
3382 BLI_assert(values_num >= 0);
3383 const int array_num = RNA_property_array_length(ptr, prop);
3384 if (values_num >= array_num) {
3385 RNA_property_int_set_array(ptr, prop, values);
3386 return;
3387 }
3388
3389 blender::Array<int, RNA_STACK_ARRAY> value_buf(array_num);
3390 RNA_property_int_get_array(ptr, prop, value_buf.data());
3391 memcpy(value_buf.data(), values, sizeof(*values) * values_num);
3392 RNA_property_int_set_array(ptr, prop, value_buf.data());
3393}
3394
3395void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
3396{
3397 int tmp[RNA_MAX_ARRAY_LENGTH];
3399
3401 BLI_assert(RNA_property_array_check(prop) != false);
3402 BLI_assert(index >= 0);
3403 BLI_assert(index < len);
3404
3405 if (len <= RNA_MAX_ARRAY_LENGTH) {
3406 RNA_property_int_get_array(ptr, prop, tmp);
3407 tmp[index] = value;
3408 RNA_property_int_set_array(ptr, prop, tmp);
3409 }
3410 else {
3411 int *tmparray;
3412
3413 tmparray = MEM_malloc_arrayN<int>(size_t(len), __func__);
3414 RNA_property_int_get_array(ptr, prop, tmparray);
3415 tmparray[index] = value;
3416 RNA_property_int_set_array(ptr, prop, tmparray);
3417 MEM_freeN(tmparray);
3418 }
3419}
3420
3422{
3424
3425 if (prop->magic != RNA_MAGIC) {
3426 const IDProperty *idprop = (const IDProperty *)prop;
3427 if (idprop->ui_data) {
3428 const IDPropertyUIDataInt *ui_data = (const IDPropertyUIDataInt *)idprop->ui_data;
3429 return ui_data->default_value;
3430 }
3431 }
3432 if (iprop->get_default) {
3433 return iprop->get_default(ptr, prop);
3434 }
3435
3436 return iprop->defaultvalue;
3437}
3438
3440{
3441 if (prop->magic == RNA_MAGIC) {
3442 return false;
3443 }
3444
3445 IDProperty *idprop = (IDProperty *)prop;
3446 BLI_assert(idprop->type == IDP_INT);
3447
3449 ui_data->default_value = value;
3450 return true;
3451}
3452
3454{
3456
3458 BLI_assert(RNA_property_array_check(prop) != false);
3459
3460 if (prop->magic != RNA_MAGIC) {
3462
3463 const IDProperty *idprop = (const IDProperty *)prop;
3464 if (idprop->ui_data) {
3465 BLI_assert(idprop->type == IDP_ARRAY);
3466 BLI_assert(idprop->subtype == IDP_INT);
3467 const IDPropertyUIDataInt *ui_data = (const IDPropertyUIDataInt *)idprop->ui_data;
3468 if (ui_data->default_array) {
3470 ui_data->default_array_len,
3471 ui_data->default_value,
3472 length,
3473 values);
3474 }
3475 else {
3477 nullptr, 0, ui_data->default_value, length, values);
3478 }
3479 }
3480 }
3481 else if (prop->arraydimension == 0) {
3482 values[0] = iprop->defaultvalue;
3483 }
3484 else {
3486 }
3487}
3488
3490{
3491 int tmp[RNA_MAX_ARRAY_LENGTH];
3493
3495 BLI_assert(RNA_property_array_check(prop) != false);
3496 BLI_assert(index >= 0);
3497 BLI_assert(index < len);
3498
3499 if (len <= RNA_MAX_ARRAY_LENGTH) {
3501 return tmp[index];
3502 }
3503 int *tmparray, value;
3504
3505 tmparray = MEM_malloc_arrayN<int>(size_t(len), __func__);
3506 RNA_property_int_get_default_array(ptr, prop, tmparray);
3507 value = tmparray[index];
3508 MEM_freeN(tmparray);
3509
3510 return value;
3511}
3512
3513static float property_float_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
3514{
3515 if (prop_rna_or_id.idprop) {
3516 IDProperty *idprop = prop_rna_or_id.idprop;
3517 if (idprop->type == IDP_FLOAT) {
3518 return IDP_float_get(idprop);
3519 }
3520 return float(IDP_double_get(idprop));
3521 }
3522 FloatPropertyRNA *fprop = reinterpret_cast<FloatPropertyRNA *>(prop_rna_or_id.rnaprop);
3523 if (fprop->get) {
3524 return fprop->get(ptr);
3525 }
3526 if (fprop->get_ex) {
3527 return fprop->get_ex(ptr, &fprop->property);
3528 }
3529 return fprop->defaultvalue;
3530}
3531
3533{
3535
3536 PropertyRNAOrID prop_rna_or_id;
3537 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3538 BLI_assert(!prop_rna_or_id.is_array);
3539 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3540 prop = nullptr;
3541 FloatPropertyRNA *fprop = reinterpret_cast<FloatPropertyRNA *>(prop_rna_or_id.rnaprop);
3542
3543 float value = property_float_get(ptr, prop_rna_or_id);
3544 if (fprop->get_transform) {
3545 value = fprop->get_transform(ptr, &fprop->property, value, prop_rna_or_id.is_set);
3546 }
3547
3548 return value;
3549}
3550
3552{
3554
3555 PropertyRNAOrID prop_rna_or_id;
3556 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3557 BLI_assert(!prop_rna_or_id.is_array);
3558 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3559 prop = nullptr;
3560 IDProperty *idprop = prop_rna_or_id.idprop;
3561 FloatPropertyRNA *fprop = reinterpret_cast<FloatPropertyRNA *>(prop_rna_or_id.rnaprop);
3562
3563 if (fprop->set_transform) {
3564 /* Get raw, untransformed (aka 'storage') value. */
3565 const float curr_value = property_float_get(ptr, prop_rna_or_id);
3566 value = fprop->set_transform(ptr, &fprop->property, value, curr_value, prop_rna_or_id.is_set);
3567 }
3568
3569 if (idprop) {
3570 RNA_property_float_clamp(ptr, &fprop->property, &value);
3571 if (idprop->type == IDP_FLOAT) {
3572 IDP_float_set(idprop, value);
3573 }
3574 else {
3575 IDP_double_set(idprop, double(value));
3576 }
3577 rna_idproperty_touch(idprop);
3578 }
3579 else if (fprop->set) {
3580 fprop->set(ptr, value);
3581 }
3582 else if (fprop->set_ex) {
3583 fprop->set_ex(ptr, &fprop->property, value);
3584 }
3585 else if (fprop->property.flag & PROP_EDITABLE) {
3586 RNA_property_float_clamp(ptr, &fprop->property, &value);
3587 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
3589 group,
3591 .release());
3592 }
3593 }
3594}
3595
3597 const float *defarr, int defarr_length, float defvalue, int out_length, float *r_values)
3598{
3599 if (defarr && defarr_length > 0) {
3600 defarr_length = std::min(defarr_length, out_length);
3601 memcpy(r_values, defarr, sizeof(float) * defarr_length);
3602 }
3603 else {
3604 defarr_length = 0;
3605 }
3606
3607 for (int i = defarr_length; i < out_length; i++) {
3608 r_values[i] = defvalue;
3609 }
3610}
3611
3615static void rna_property_float_fill_default_array_values_double(const double *default_array,
3616 const int default_array_len,
3617 const double default_value,
3618 const int out_length,
3619 float *r_values)
3620{
3621 const int array_copy_len = std::min(out_length, default_array_len);
3622
3623 for (int i = 0; i < array_copy_len; i++) {
3624 r_values[i] = float(default_array[i]);
3625 }
3626
3627 for (int i = array_copy_len; i < out_length; i++) {
3628 r_values[i] = float(default_value);
3629 }
3630}
3631
3633 FloatPropertyRNA *fprop,
3634 float *r_values)
3635{
3636 if (ptr->data && fprop->get_default_array) {
3637 fprop->get_default_array(ptr, &fprop->property, r_values);
3638 return;
3639 }
3640
3641 int length = fprop->property.totarraylength;
3642 int out_length = RNA_property_array_length(ptr, &fprop->property);
3643
3645 fprop->defaultarray, length, fprop->defaultvalue, out_length, r_values);
3646}
3647
3649 PropertyRNAOrID &prop_rna_or_id,
3651{
3652 PropertyRNA *rna_prop = prop_rna_or_id.rnaprop;
3653 FloatPropertyRNA *fprop = reinterpret_cast<FloatPropertyRNA *>(rna_prop);
3654 if (prop_rna_or_id.idprop) {
3655 IDProperty *idprop = prop_rna_or_id.idprop;
3656 BLI_assert(idprop->len == RNA_property_array_length(ptr, rna_prop) ||
3657 (rna_prop->flag & PROP_IDPROPERTY));
3658 if (rna_prop->arraydimension == 0) {
3659 r_values[0] = RNA_property_float_get(ptr, rna_prop);
3660 }
3661 else if (idprop->subtype == IDP_FLOAT) {
3662 memcpy(r_values.data(),
3663 IDP_array_float_get(idprop),
3664 sizeof(decltype(r_values)::value_type) * idprop->len);
3665 }
3666 else {
3667 double *src_values = IDP_array_double_get(idprop);
3668 for (int i = 0; i < idprop->len; i++) {
3669 r_values[i] = float(src_values[i]);
3670 }
3671 }
3672 }
3673 else if (rna_prop->arraydimension == 0) {
3674 r_values[0] = RNA_property_float_get(ptr, rna_prop);
3675 }
3676 else if (fprop->getarray) {
3677 fprop->getarray(ptr, r_values.data());
3678 }
3679 else if (fprop->getarray_ex) {
3680 fprop->getarray_ex(ptr, rna_prop, r_values.data());
3681 }
3682 else {
3684 }
3685}
3686
3688{
3690 BLI_assert(RNA_property_array_check(prop) != false);
3691
3692 PropertyRNAOrID prop_rna_or_id;
3693 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3694 BLI_assert(prop_rna_or_id.is_array);
3695 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3696 prop = nullptr;
3697 FloatPropertyRNA *fprop = reinterpret_cast<FloatPropertyRNA *>(prop_rna_or_id.rnaprop);
3698
3699 blender::MutableSpan<float> r_values(values, int64_t(prop_rna_or_id.array_len));
3700 values = nullptr; /* Do not access this 'raw' pointer anymore in code below. */
3701 property_float_get_array(ptr, prop_rna_or_id, r_values);
3702 if (fprop->getarray_transform) {
3703 /* NOTE: Given current implementation, it would _probably_ be safe to use `values` for both
3704 * input 'current values' and output 'final values', since python will make a copy of the input
3705 * anyways. Think it's better to keep it clean and make a copy here to avoid any potential
3706 * issues in the future though. */
3707 blender::Array<float, RNA_STACK_ARRAY> curr_values(r_values.as_span());
3708 fprop->getarray_transform(
3709 ptr, &fprop->property, curr_values.data(), prop_rna_or_id.is_set, r_values.data());
3710 }
3711}
3712
3714 PropertyRNA *prop,
3715 float *values,
3716 int values_num)
3717{
3718 BLI_assert(values_num >= 0);
3719 const int array_num = RNA_property_array_length(ptr, prop);
3720 if (values_num >= array_num) {
3721 RNA_property_float_get_array(ptr, prop, values);
3722 return;
3723 }
3724
3725 blender::Array<float, RNA_STACK_ARRAY> value_buf(array_num);
3726 RNA_property_float_get_array(ptr, prop, value_buf.data());
3727 memcpy(values, value_buf.data(), sizeof(*values) * values_num);
3728}
3729
3731{
3732 const int array_len = RNA_property_array_length(ptr, prop);
3733
3734 if (array_len <= 0) {
3735 values[0] = 0.0f;
3736 values[1] = 0.0f;
3737 }
3738 else if (array_len == 1) {
3739 RNA_property_float_get_array(ptr, prop, values);
3740 values[1] = values[0];
3741 }
3742 else {
3743 float arr_stack[32];
3744 float *arr;
3745 int i;
3746
3747 if (array_len > 32) {
3748 arr = MEM_malloc_arrayN<float>(size_t(array_len), __func__);
3749 }
3750 else {
3751 arr = arr_stack;
3752 }
3753
3755 values[0] = values[1] = arr[0];
3756 for (i = 1; i < array_len; i++) {
3757 values[0] = std::min(values[0], arr[i]);
3758 values[1] = std::max(values[1], arr[i]);
3759 }
3760
3761 if (arr != arr_stack) {
3762 MEM_freeN(arr);
3763 }
3764 }
3765}
3766
3768{
3769 float tmp[RNA_MAX_ARRAY_LENGTH];
3771
3773 BLI_assert(RNA_property_array_check(prop) != false);
3774 BLI_assert(index >= 0);
3775 BLI_assert(index < len);
3776
3777 if (len <= RNA_MAX_ARRAY_LENGTH) {
3779 return tmp[index];
3780 }
3781 float *tmparray, value;
3782
3783 tmparray = MEM_malloc_arrayN<float>(size_t(len), __func__);
3784 RNA_property_float_get_array(ptr, prop, tmparray);
3785 value = tmparray[index];
3786 MEM_freeN(tmparray);
3787
3788 return value;
3789}
3790
3791void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
3792{
3794
3795 PropertyRNAOrID prop_rna_or_id;
3796 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
3797 BLI_assert(prop_rna_or_id.is_array);
3798 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
3799 prop = nullptr;
3800 IDProperty *idprop = prop_rna_or_id.idprop;
3801 PropertyRNA *rna_prop = prop_rna_or_id.rnaprop;
3802 FloatPropertyRNA *fprop = reinterpret_cast<FloatPropertyRNA *>(rna_prop);
3803
3804 const int64_t values_num = int64_t(prop_rna_or_id.array_len);
3805 blender::Span<float> final_values(values, values_num);
3806 values = nullptr; /* Do not access this 'raw' pointer anymore in code below. */
3807 /* Default init does not allocate anything, so it's cheap. This is only reinitialized with actual
3808 * `values_num` items if `setarray_transform` is called. */
3809 blender::Array<float, RNA_STACK_ARRAY> final_values_storage{};
3810 if (fprop->setarray_transform) {
3811 /* Get raw, untransformed (aka 'storage') value. */
3812 blender::Array<float, RNA_STACK_ARRAY> curr_values(values_num);
3813 property_float_get_array(ptr, prop_rna_or_id, curr_values.as_mutable_span());
3814
3815 final_values_storage.reinitialize(values_num);
3816 fprop->setarray_transform(ptr,
3817 rna_prop,
3818 final_values.data(),
3819 curr_values.data(),
3820 prop_rna_or_id.is_set,
3821 final_values_storage.data());
3822 final_values = final_values_storage.as_span();
3823 }
3824
3825 if (idprop) {
3826 BLI_assert(idprop->len == values_num);
3827 if (rna_prop->arraydimension == 0) {
3828 if (idprop->type == IDP_FLOAT) {
3829 IDP_float_set(idprop, final_values[0]);
3830 }
3831 else {
3832 IDP_double_set(idprop, double(final_values[0]));
3833 }
3834 }
3835 else if (idprop->subtype == IDP_FLOAT) {
3836 memcpy(IDP_array_float_get(idprop),
3837 final_values.data(),
3838 sizeof(decltype(final_values)::value_type) * idprop->len);
3839 }
3840 else {
3841 double *dst_values = IDP_array_double_get(idprop);
3842 for (int i = 0; i < idprop->len; i++) {
3843 dst_values[i] = double(final_values[i]);
3844 }
3845 }
3846
3847 rna_idproperty_touch(idprop);
3848 }
3849 else if (rna_prop->arraydimension == 0) {
3850 RNA_property_float_set(ptr, rna_prop, final_values[0]);
3851 }
3852 else if (fprop->setarray) {
3853 fprop->setarray(ptr, final_values.data());
3854 }
3855 else if (fprop->setarray_ex) {
3856 fprop->setarray_ex(ptr, rna_prop, final_values.data());
3857 }
3858 else if (rna_prop->flag & PROP_EDITABLE) {
3859 // RNA_property_float_clamp_array(ptr, prop, &value); /* TODO. */
3860 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
3861 IDP_AddToGroup(group,
3863 prop_rna_or_id.identifier, final_values, IDP_FLAG_STATIC_TYPE)
3864 .release());
3865 }
3866 }
3867}
3868
3870 PropertyRNA *prop,
3871 const float *values,
3872 int values_num)
3873{
3874 BLI_assert(values_num >= 0);
3875 const int array_num = RNA_property_array_length(ptr, prop);
3876 if (values_num >= array_num) {
3877 RNA_property_float_set_array(ptr, prop, values);
3878 return;
3879 }
3880
3881 blender::Array<float, RNA_STACK_ARRAY> value_buf(array_num);
3882 RNA_property_float_get_array(ptr, prop, value_buf.data());
3883 memcpy(value_buf.data(), values, sizeof(*values) * values_num);
3884 RNA_property_float_set_array(ptr, prop, value_buf.data());
3885}
3886
3887void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
3888{
3889 float tmp[RNA_MAX_ARRAY_LENGTH];
3891
3893 BLI_assert(RNA_property_array_check(prop) != false);
3894 BLI_assert(index >= 0);
3895 BLI_assert(index < len);
3896
3897 if (len <= RNA_MAX_ARRAY_LENGTH) {
3899 tmp[index] = value;
3901 }
3902 else {
3903 float *tmparray;
3904
3905 tmparray = MEM_malloc_arrayN<float>(size_t(len), __func__);
3906 RNA_property_float_get_array(ptr, prop, tmparray);
3907 tmparray[index] = value;
3908 RNA_property_float_set_array(ptr, prop, tmparray);
3909 MEM_freeN(tmparray);
3910 }
3911}
3912
3914{
3916
3918 BLI_assert(RNA_property_array_check(prop) == false);
3919
3920 if (prop->magic != RNA_MAGIC) {
3921 const IDProperty *idprop = (const IDProperty *)prop;
3922 if (idprop->ui_data) {
3924 const IDPropertyUIDataFloat *ui_data = (const IDPropertyUIDataFloat *)idprop->ui_data;
3925 return float(ui_data->default_value);
3926 }
3927 }
3928 if (fprop->get_default) {
3929 return fprop->get_default(ptr, prop);
3930 }
3931
3932 return fprop->defaultvalue;
3933}
3934
3936{
3937 if (prop->magic == RNA_MAGIC) {
3938 return false;
3939 }
3940
3941 IDProperty *idprop = (IDProperty *)prop;
3942 BLI_assert(idprop->type == IDP_FLOAT);
3943
3945 ui_data->default_value = double(value);
3946 return true;
3947}
3948
3950{
3952
3954 BLI_assert(RNA_property_array_check(prop) != false);
3955
3956 if (prop->magic != RNA_MAGIC) {
3958
3959 const IDProperty *idprop = (const IDProperty *)prop;
3960 if (idprop->ui_data) {
3961 BLI_assert(idprop->type == IDP_ARRAY);
3963 const IDPropertyUIDataFloat *ui_data = (const IDPropertyUIDataFloat *)idprop->ui_data;
3965 ui_data->default_array_len,
3966 ui_data->default_value,
3967 length,
3968 values);
3969 }
3970 }
3971 else if (prop->arraydimension == 0) {
3972 values[0] = fprop->defaultvalue;
3973 }
3974 else {
3976 }
3977}
3978
3980{
3981 float tmp[RNA_MAX_ARRAY_LENGTH];
3983
3985 BLI_assert(RNA_property_array_check(prop) != false);
3986 BLI_assert(index >= 0);
3987 BLI_assert(index < len);
3988
3989 if (len <= RNA_MAX_ARRAY_LENGTH) {
3991 return tmp[index];
3992 }
3993 float *tmparray, value;
3994
3995 tmparray = MEM_malloc_arrayN<float>(size_t(len), __func__);
3997 value = tmparray[index];
3998 MEM_freeN(tmparray);
3999
4000 return value;
4001}
4002
4004{
4005 if (prop_rna_or_id.idprop) {
4006 IDProperty *idprop = prop_rna_or_id.idprop;
4007 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
4008 return size_t(idprop->len);
4009 }
4010 /* these _must_ stay in sync */
4011 if (strlen(IDP_string_get(idprop)) != idprop->len - 1) {
4012 printf("%zu vs. %d\n", strlen(IDP_string_get(idprop)), idprop->len - 1);
4013 }
4014 BLI_assert(strlen(IDP_string_get(idprop)) == idprop->len - 1);
4015 return size_t(idprop->len - 1);
4016 }
4017
4018 StringPropertyRNA *sprop = reinterpret_cast<StringPropertyRNA *>(prop_rna_or_id.rnaprop);
4019 if (sprop->length) {
4020 return sprop->length(ptr);
4021 }
4022 if (sprop->length_ex) {
4023 return size_t(sprop->length_ex(ptr, &sprop->property));
4024 }
4025 return strlen(sprop->defaultvalue);
4026}
4027
4028static std::string property_string_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
4029{
4030 if (prop_rna_or_id.idprop) {
4031 const size_t length = property_string_length_storage(ptr, prop_rna_or_id);
4032 return std::string{IDP_string_get(prop_rna_or_id.idprop), length};
4033 }
4034 StringPropertyRNA *sprop = reinterpret_cast<StringPropertyRNA *>(prop_rna_or_id.rnaprop);
4035 if (sprop->get) {
4036 const size_t length = property_string_length_storage(ptr, prop_rna_or_id);
4037 /* Note: after `resize()` the underlying buffer is actually at least
4038 * `length + 1` bytes long, because (since C++11) `std::string` guarantees
4039 * a terminating null byte, but that is not considered part of the length. */
4040 std::string string_ret;
4041 string_ret.resize(length);
4042
4043 sprop->get(ptr, string_ret.data());
4044 return string_ret;
4045 }
4046 if (sprop->get_ex) {
4047 return sprop->get_ex(ptr, &sprop->property);
4048 }
4049 return sprop->defaultvalue;
4050}
4051
4053{
4055 PropertyRNAOrID prop_rna_or_id;
4056 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
4057 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
4058 prop = nullptr;
4059 StringPropertyRNA *sprop = reinterpret_cast<StringPropertyRNA *>(prop_rna_or_id.rnaprop);
4060
4061 std::string string_ret = property_string_get(ptr, prop_rna_or_id);
4062 if (sprop->get_transform) {
4063 string_ret = sprop->get_transform(ptr, &sprop->property, string_ret, prop_rna_or_id.is_set);
4064 }
4065
4066 BLI_assert_msg(!sprop->maxlength || string_ret.size() < sprop->maxlength,
4067 "Returned string exceeds the property's max length");
4068
4069 return string_ret;
4070}
4071
4073{
4074 const std::string string_ret = RNA_property_string_get(ptr, prop);
4075
4076 memcpy(value, string_ret.c_str(), string_ret.size() + 1);
4077}
4078
4080 PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
4081{
4082 if (fixedbuf) {
4083 BLI_string_debug_size(fixedbuf, fixedlen);
4084 }
4085
4086 const std::string string_ret = RNA_property_string_get(ptr, prop);
4087
4088 char *buf;
4089 if (string_ret.size() < fixedlen) {
4090 buf = fixedbuf;
4091 }
4092 else {
4093 buf = MEM_malloc_arrayN<char>(string_ret.size() + 1, __func__);
4094 }
4095
4096 memcpy(buf, string_ret.c_str(), string_ret.size() + 1);
4097 if (r_len) {
4098 *r_len = int(string_ret.size());
4099 }
4100
4101 return buf;
4102}
4103
4105{
4107 PropertyRNAOrID prop_rna_or_id;
4108 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
4109 prop = nullptr;
4110 /* NOTE: `prop` is kept unchanged, to allow e.g. call to `RNA_property_string_get` without
4111 * further complications.
4112 * `sprop->property` should be used when access to an actual RNA property is required.
4113 */
4114 StringPropertyRNA *sprop = reinterpret_cast<StringPropertyRNA *>(prop_rna_or_id.rnaprop);
4115
4116 /* If there is a `get_transform` callback, no choice but get that final string to find out its
4117 * length. Otherwise, get the 'storage length', which is typically more efficient to compute. */
4118 if (sprop->get_transform) {
4119 std::string string_final = property_string_get(ptr, prop_rna_or_id);
4120 return int(string_final.size());
4121 }
4122 return int(property_string_length_storage(ptr, prop_rna_or_id));
4123}
4124
4125void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
4126{
4128 PropertyRNAOrID prop_rna_or_id;
4129 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
4130 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
4131 prop = nullptr;
4132 IDProperty *idprop = prop_rna_or_id.idprop;
4133 StringPropertyRNA *sprop = reinterpret_cast<StringPropertyRNA *>(prop_rna_or_id.rnaprop);
4134
4135 /* Value can be nullptr, see #145562. */
4136 /* FIXME: unclear if this function is supposed to accept nullptr values? */
4137 std::string value_set = value ? value : "";
4138 if (sprop->set_transform) {
4139 /* Get raw, untransformed (aka 'storage') value. */
4140 const std::string curr_value = property_string_get(ptr, prop_rna_or_id);
4141 value_set = sprop->set_transform(
4142 ptr, &sprop->property, value_set, curr_value, prop_rna_or_id.is_set);
4143 }
4144
4145 if (idprop) {
4146 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
4148 idprop, value_set.c_str(), RNA_property_string_maxlength(&sprop->property));
4149 rna_idproperty_touch(idprop);
4150 }
4151 else if (sprop->set) {
4152 sprop->set(ptr, value_set.c_str()); /* set function needs to clamp itself */
4153 }
4154 else if (sprop->set_ex) {
4155 sprop->set_ex(ptr, &sprop->property, value_set); /* set function needs to clamp itself */
4156 }
4157 else if (sprop->property.flag & PROP_EDITABLE) {
4158 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
4159 IDP_AddToGroup(group,
4160 IDP_NewStringMaxSize(value_set.c_str(),
4162 prop_rna_or_id.identifier,
4164 }
4165 }
4166}
4167
4168void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const char *value, int len)
4169{
4172 PropertyRNAOrID prop_rna_or_id;
4173 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
4174 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
4175 prop = nullptr;
4176 IDProperty *idprop = prop_rna_or_id.idprop;
4177 StringPropertyRNA *sprop = reinterpret_cast<StringPropertyRNA *>(prop_rna_or_id.rnaprop);
4178
4179 std::string value_set = {value, size_t(len)};
4180 if (sprop->set_transform) {
4181 /* Get raw, untransformed (aka 'storage') value. */
4182 const std::string curr_value = property_string_get(ptr, prop_rna_or_id);
4183 value_set = sprop->set_transform(
4184 ptr, &sprop->property, value_set, curr_value, prop_rna_or_id.is_set);
4185 }
4186
4187 if (idprop) {
4188 IDP_ResizeArray(idprop, value_set.size() + 1);
4189 memcpy(idprop->data.pointer, value, value_set.size() + 1);
4190 rna_idproperty_touch(idprop);
4191 }
4192 else if (sprop->set) {
4193 sprop->set(ptr, value_set.c_str()); /* set function needs to clamp itself */
4194 }
4195 else if (sprop->set_ex) {
4196 sprop->set_ex(ptr, &sprop->property, value_set); /* set function needs to clamp itself */
4197 }
4198 else if (sprop->property.flag & PROP_EDITABLE) {
4199 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
4200 IDPropertyTemplate val = {0};
4201 val.string.str = value_set.c_str();
4202 val.string.len = value_set.size() + 1;
4204 IDP_AddToGroup(group,
4205 IDP_New(IDP_STRING, &val, prop_rna_or_id.identifier, IDP_FLAG_STATIC_TYPE));
4206 }
4207 }
4208}
4209
4210void RNA_property_string_get_default(PropertyRNA *prop, char *value, const int value_maxncpy)
4211{
4213
4214 if (prop->magic != RNA_MAGIC) {
4215 const IDProperty *idprop = (const IDProperty *)prop;
4216 if (idprop->ui_data) {
4217 BLI_assert(idprop->type == IDP_STRING);
4218 const IDPropertyUIDataString *ui_data = (const IDPropertyUIDataString *)idprop->ui_data;
4219 BLI_strncpy(value, ui_data->default_value, value_maxncpy);
4220 return;
4221 }
4222
4223 strcpy(value, "");
4224 return;
4225 }
4226
4228
4229 strcpy(value, sprop->defaultvalue);
4230}
4231
4233 PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
4234{
4235 char *buf;
4236 int length;
4237
4239
4241
4242 if (length + 1 < fixedlen) {
4243 buf = fixedbuf;
4244 }
4245 else {
4246 buf = MEM_calloc_arrayN<char>(size_t(length) + 1, __func__);
4247 }
4248
4250
4251 if (r_len) {
4252 *r_len = length;
4253 }
4254
4255 return buf;
4256}
4257
4259{
4261
4262 if (prop->magic != RNA_MAGIC) {
4263 const IDProperty *idprop = (const IDProperty *)prop;
4264 if (idprop->ui_data) {
4265 BLI_assert(idprop->type == IDP_STRING);
4266 const IDPropertyUIDataString *ui_data = (const IDPropertyUIDataString *)idprop->ui_data;
4267 if (ui_data->default_value != nullptr) {
4268 return strlen(ui_data->default_value);
4269 }
4270 }
4271
4272 return 0;
4273 }
4274
4276
4277 return strlen(sprop->defaultvalue);
4278}
4279
4281{
4283 if (prop->magic != RNA_MAGIC) {
4284 return eStringPropertySearchFlag(0);
4285 }
4287 if (sprop->search) {
4289 }
4290 else {
4291 BLI_assert(sprop->search_flag == 0);
4292 }
4293 return sprop->search_flag;
4294}
4295
4297 const bContext *C,
4298 PointerRNA *ptr,
4299 PropertyRNA *prop,
4300 const char *edit_text,
4302{
4305 sprop->search(C, ptr, prop, edit_text, visit_fn);
4306}
4307
4308std::optional<std::string> RNA_property_string_path_filter(const bContext *C,
4309 PointerRNA *ptr,
4310 PropertyRNA *prop)
4311{
4313 PropertyRNA *rna_prop = rna_ensure_property(prop);
4314 StringPropertyRNA *sprop = (StringPropertyRNA *)rna_prop;
4315 if (!sprop->path_filter) {
4316 return std::nullopt;
4317 }
4318 return sprop->path_filter(C, ptr, rna_prop);
4319}
4320
4322{
4323 if (prop_rna_or_id.idprop) {
4324 return IDP_int_get(prop_rna_or_id.idprop);
4325 }
4326 EnumPropertyRNA *eprop = reinterpret_cast<EnumPropertyRNA *>(prop_rna_or_id.rnaprop);
4327 if (eprop->get) {
4328 return eprop->get(ptr);
4329 }
4330 if (eprop->get_ex) {
4331 return eprop->get_ex(ptr, &eprop->property);
4332 }
4333 return eprop->defaultvalue;
4334}
4335
4337{
4339
4340 PropertyRNAOrID prop_rna_or_id;
4341 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
4342 BLI_assert(!prop_rna_or_id.is_array);
4343 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
4344 prop = nullptr;
4345 EnumPropertyRNA *eprop = reinterpret_cast<EnumPropertyRNA *>(prop_rna_or_id.rnaprop);
4346
4347 int value = property_enum_get(ptr, prop_rna_or_id);
4348 if (eprop->get_transform) {
4349 value = eprop->get_transform(ptr, &eprop->property, value, prop_rna_or_id.is_set);
4350 }
4351
4352 return value;
4353}
4354
4356{
4358
4359 PropertyRNAOrID prop_rna_or_id;
4360 rna_property_rna_or_id_get(prop, ptr, &prop_rna_or_id);
4361 BLI_assert(!prop_rna_or_id.is_array);
4362 /* Make initial `prop` pointer invalid, to ensure that it is not used anywhere below. */
4363 prop = nullptr;
4364 IDProperty *idprop = prop_rna_or_id.idprop;
4365 EnumPropertyRNA *eprop = reinterpret_cast<EnumPropertyRNA *>(prop_rna_or_id.rnaprop);
4366
4367 if (eprop->set_transform) {
4368 /* Get raw, untransformed (aka 'storage') value. */
4369 const int curr_value = property_enum_get(ptr, prop_rna_or_id);
4370 value = eprop->set_transform(ptr, &eprop->property, value, curr_value, prop_rna_or_id.is_set);
4371 }
4372
4373 if (idprop) {
4374 IDP_int_set(idprop, value);
4375 rna_idproperty_touch(idprop);
4376 }
4377 else if (eprop->set) {
4378 eprop->set(ptr, value);
4379 }
4380 else if (eprop->set_ex) {
4381 eprop->set_ex(ptr, &eprop->property, value);
4382 }
4383 else if (eprop->property.flag & PROP_EDITABLE) {
4384 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
4386 group,
4388 .release());
4389 }
4390 }
4391}
4392
4394{
4397
4398 if (prop->magic != RNA_MAGIC) {
4399 const IDProperty *idprop = reinterpret_cast<const IDProperty *>(prop);
4400 if (idprop->ui_data) {
4401 BLI_assert(idprop->type == IDP_INT);
4402 const IDPropertyUIDataInt *ui_data = reinterpret_cast<const IDPropertyUIDataInt *>(
4403 idprop->ui_data);
4404 return ui_data->default_value;
4405 }
4406 }
4407 if (eprop->get_default) {
4408 return eprop->get_default(ptr, prop);
4409 }
4410
4411 return eprop->defaultvalue;
4412}
4413
4415 const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
4416{
4417 const EnumPropertyItem *item_array;
4418 int totitem;
4419 bool free;
4420 int result_value = from_value;
4421 int i, i_init;
4422 int single_step = (step < 0) ? -1 : 1;
4423 int step_tot = 0;
4424
4425 RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
4426 i = RNA_enum_from_value(item_array, from_value);
4427 i_init = i;
4428
4429 do {
4430 i = mod_i(i + single_step, totitem);
4431 if (item_array[i].identifier[0]) {
4432 step_tot += single_step;
4433 }
4434 } while ((i != i_init) && (step_tot != step));
4435
4436 if (i != i_init) {
4437 result_value = item_array[i].value;
4438 }
4439
4440 if (free) {
4441 MEM_freeN(item_array);
4442 }
4443
4444 return result_value;
4445}
4446
4447static PointerRNA property_pointer_get(PointerRNA *ptr, PropertyRNA *prop, const bool do_create)
4448{
4449 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
4450 IDProperty *idprop;
4451
4452 static blender::Mutex mutex;
4453
4455
4456 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4457 pprop = (PointerPropertyRNA *)prop;
4458
4459 if (RNA_struct_is_ID(pprop->type)) {
4460 /* ID PointerRNA should not have ancestors currently. */
4461 return RNA_id_pointer_create(idprop->type == IDP_GROUP ? nullptr : IDP_ID_get(idprop));
4462 }
4463
4464 /* for groups, data is idprop itself */
4465 if (pprop->type_fn) {
4466 return RNA_pointer_create_with_parent(*ptr, pprop->type_fn(ptr), idprop);
4467 }
4468 return RNA_pointer_create_with_parent(*ptr, pprop->type, idprop);
4469 }
4470 if (pprop->get) {
4471 return pprop->get(ptr);
4472 }
4473 if (prop->flag & PROP_IDPROPERTY && do_create) {
4474 /* NOTE: While creating/writing data in an accessor is really bad design-wise, this is
4475 * currently very difficult to avoid in that case. So a global mutex is used to keep ensuring
4476 * thread safety. */
4477 std::scoped_lock lock(mutex);
4478 /* NOTE: We do not need to check again for existence of the pointer after locking here, since
4479 * this is also done in #RNA_property_pointer_add itself. */
4481 return RNA_property_pointer_get(ptr, prop);
4482 }
4483 return PointerRNA_NULL;
4484}
4485
4490
4495
4497 PropertyRNA *prop,
4498 PointerRNA ptr_value,
4499 ReportList *reports)
4500{
4501 /* Detect IDProperty and retrieve the actual PropertyRNA pointer before cast. */
4502 IDProperty *idprop = rna_idproperty_check(&prop, ptr);
4503
4504 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
4506
4507 /* This is a 'real' RNA property, not an IDProperty or a dynamic RNA property using an IDProperty
4508 * as backend storage. */
4509 if (pprop->set) {
4510 if (ptr_value.type != nullptr && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
4511 BKE_reportf(reports,
4512 RPT_ERROR,
4513 "%s: expected %s type, not %s",
4514 __func__,
4515 pprop->type->identifier,
4516 ptr_value.type->identifier);
4517 return;
4518 }
4519
4520#ifndef NDEBUG
4521 /* NOTE: By design, it can be safely assumed that both old and new ID pointers are valid when
4522 * accessed through RNA. Handling of invalid ID pointers, e.g. freed ones etc., should never
4523 * happen through RNA code, but directly on underlying (DNA) data.
4524 *
4525 * Setters are also not expected to free or otherwise invalidate ID pointers. So storing them
4526 * here should be safe. */
4527 BLI_assert(pprop->get);
4528 const bool is_id_refcounting = (prop->flag & PROP_ID_REFCOUNT) != 0;
4529
4530 const PointerRNA old_id_ptr = pprop->get(ptr);
4531 BLI_assert_msg(!is_id_refcounting || !old_id_ptr.data || RNA_struct_is_ID(old_id_ptr.type),
4532 "If the property is tagged with ID reference-counting, "
4533 "its current value should be null or an ID");
4534 const ID *old_id = (old_id_ptr.type && RNA_struct_is_ID(old_id_ptr.type)) ?
4535 old_id_ptr.data_as<ID>() :
4536 nullptr;
4537 const int old_id_old_refcount = old_id ? ID_REFCOUNTING_USERS(old_id) : 0;
4538
4539 const ID *new_id = (ptr_value.type && RNA_struct_is_ID(ptr_value.type)) ?
4540 ptr_value.data_as<ID>() :
4541 nullptr;
4542 const int new_id_old_refcount = new_id ? ID_REFCOUNTING_USERS(new_id) : 0;
4543#endif
4544
4545 if (!((prop->flag & PROP_NEVER_NULL) && ptr_value.data == nullptr) &&
4546 !((prop->flag & PROP_ID_SELF_CHECK) && ptr->owner_id == ptr_value.owner_id))
4547 {
4548 pprop->set(ptr, ptr_value, reports);
4549 }
4550
4551#ifndef NDEBUG
4552 /* NOTE: Current checks are relatively flexible, but do expect 'reasonable' behavior (ID
4553 * handling) from custom setters.
4554 *
4555 * Should there be some very uncommon setter behavior, e.g. unassigning an ID from the property
4556 * automatically assigning it to several other reference-counting usages, this will have to be
4557 * tweaked, e.g. by adding a special 'skip checks' flag to such RNA properties. */
4558 PointerRNA current_id_ptr = pprop->get(ptr);
4560 !is_id_refcounting || !current_id_ptr.data || RNA_struct_is_ID(current_id_ptr.type),
4561 "If the property is tagged with ID reference-counting, its current value should be "
4562 "null or an ID");
4563 ID *current_id = (current_id_ptr.type && RNA_struct_is_ID(current_id_ptr.type)) ?
4564 static_cast<ID *>(current_id_ptr.data) :
4565 nullptr;
4566
4567 if (old_id) {
4568 const int old_id_new_refcount = ID_REFCOUNTING_USERS(old_id);
4569 if (ELEM(old_id, new_id, current_id)) {
4570 BLI_assert_msg(old_id_new_refcount == old_id_old_refcount,
4571 "Reassigning the same ID to a RNA pointer property, or assignment failure, "
4572 "should not modify the original ID user-count");
4573 }
4574 else if (is_id_refcounting) {
4576 old_id_new_refcount < old_id_old_refcount,
4577 "Unassigning an ID from a reference-counting RNA pointer property should decrease "
4578 "its user-count");
4579 }
4580 else {
4582 old_id_new_refcount == old_id_old_refcount,
4583 "Unassigning an ID from a non-reference-counting RNA pointer property should not "
4584 "modify its user-count");
4585 }
4586 }
4587 if (new_id && new_id != old_id) {
4588 const int new_id_new_refcount = ID_REFCOUNTING_USERS(new_id);
4589 if (current_id == old_id) {
4590 BLI_assert_msg(new_id_new_refcount == new_id_old_refcount,
4591 "Failed assigning a new ID to a RNA pointer property, should not modify "
4592 "the new ID user-count");
4593 }
4594 else if (is_id_refcounting) {
4596 new_id_new_refcount > new_id_old_refcount,
4597 "Assigning an ID to a reference-counting RNA pointer property should increase "
4598 "its user-count");
4599 }
4600 else {
4602 new_id_new_refcount == new_id_old_refcount,
4603 "Assigning an ID to a non-reference-counting RNA pointer property should not "
4604 "modify its user-count");
4605 }
4606 }
4607#endif
4608
4609 return;
4610 }
4611
4612 /* Assigning to an IDProperty. */
4613 ID *value = static_cast<ID *>(ptr_value.data);
4614
4615 if (ptr_value.type != nullptr && !RNA_struct_is_a(ptr_value.type, &RNA_ID)) {
4617 reports, RPT_ERROR, "%s: expected ID type, not %s", __func__, ptr_value.type->identifier);
4618 return;
4619 }
4620 if (value && (value->flag & ID_FLAG_EMBEDDED_DATA) != 0) {
4621 BKE_reportf(reports, RPT_ERROR, "%s: cannot assign an embedded ID to an IDProperty", __func__);
4622 return;
4623 }
4624
4625 /* We got an existing IDProperty. */
4626 if (idprop != nullptr) {
4627 /* Not-yet-defined ID IDProps have an IDP_GROUP type, not an IDP_ID one - because of reasons?
4628 * XXX This has to be investigated fully - there might be a good reason for it, but off hands
4629 * this seems really weird... */
4630 if (idprop->type == IDP_ID) {
4631 IDP_AssignID(idprop, value, 0);
4632 rna_idproperty_touch(idprop);
4633 }
4634 else {
4635 BLI_assert(idprop->type == IDP_GROUP);
4637 BLI_assert(group != nullptr);
4638
4640 group,
4641 blender::bke::idprop::create(idprop->name, value, IDP_FLAG_STATIC_TYPE).release(),
4642 idprop,
4643 0);
4644 }
4645 }
4646 /* IDProperty disguised as RNA property (and not yet defined in ptr). */
4647 else if (prop->flag & PROP_EDITABLE) {
4648 if (IDProperty *group = RNA_struct_system_idprops(ptr, true)) {
4650 group,
4652 }
4653 }
4654}
4655
4657{
4658 // PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
4659
4660 // BLI_assert(RNA_property_type(prop) == PROP_POINTER);
4661
4662 return PointerRNA_NULL; /* FIXME: there has to be a way... */
4663}
4664
4666{
4667 // IDProperty *idprop;
4668
4670
4671 if (/*idprop=*/rna_idproperty_check(&prop, ptr)) {
4672 /* already exists */
4673 }
4674 else if (prop->flag & PROP_IDPROPERTY) {
4675 IDProperty *group;
4676
4677 group = RNA_struct_system_idprops(ptr, true);
4678 if (group) {
4680 group,
4682 }
4683 }
4684 else {
4685 printf("%s %s.%s: only supported for id properties.\n",
4686 __func__,
4687 ptr->type->identifier,
4688 prop->identifier);
4689 }
4690}
4691
4693{
4694 IDProperty *idprop, *group;
4695
4697
4698 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4699 group = RNA_struct_system_idprops(ptr, false);
4700
4701 if (group) {
4702 IDP_FreeFromGroup(group, idprop);
4703 }
4704 }
4705 else {
4706 printf("%s %s.%s: only supported for id properties.\n",
4707 __func__,
4708 ptr->type->identifier,
4709 prop->identifier);
4710 }
4711}
4712
4720
4722 PropertyRNA *prop,
4724{
4725 IDProperty *idprop;
4726
4728
4729 *iter = {};
4730
4731 if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
4732 iter->parent = *ptr;
4733 iter->prop = prop;
4734
4735 if (idprop) {
4737 ptr,
4738 IDP_property_array_get(idprop),
4739 sizeof(IDProperty),
4740 idprop->len,
4741 false,
4742 nullptr);
4743 }
4744 else {
4745 rna_iterator_array_begin(iter, ptr, nullptr, sizeof(IDProperty), 0, false, nullptr);
4746 }
4747
4748 if (iter->valid) {
4750 }
4751
4752 iter->idprop = 1;
4753 }
4754 else {
4756 cprop->begin(iter, ptr);
4757 }
4758}
4759
4761{
4763
4764 if (iter->idprop) {
4766
4767 if (iter->valid) {
4769 }
4770 }
4771 else {
4772 cprop->next(iter);
4773 }
4774}
4775
4777{
4779 int i;
4780
4781 if (num > 1 && (iter->idprop || (cprop->property.flag_internal & PROP_INTERN_RAW_ARRAY))) {
4782 /* fast skip for array */
4783 ArrayIterator *internal = &iter->internal.array;
4784
4785 if (!internal->skip) {
4786 internal->ptr += internal->itemsize * (num - 1);
4787 iter->valid = (internal->ptr < internal->endptr);
4788 if (iter->valid) {
4790 }
4791 return;
4792 }
4793 }
4794
4795 /* slow iteration otherwise */
4796 for (i = 0; i < num && iter->valid; i++) {
4798 }
4799}
4800
4802{
4804
4805 if (iter->idprop) {
4807 }
4808 else {
4809 cprop->end(iter);
4810 }
4811}
4812
4814{
4816 IDProperty *idprop;
4817
4819
4820 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4821 return idprop->len;
4822 }
4823 if (cprop->length) {
4824 return cprop->length(ptr);
4825 }
4827 int length = 0;
4828
4829 RNA_property_collection_begin(ptr, prop, &iter);
4830 for (; iter.valid; RNA_property_collection_next(&iter)) {
4831 length++;
4832 }
4834
4835 return length;
4836}
4837
4839{
4842 RNA_property_collection_begin(ptr, prop, &iter);
4843 bool test = iter.valid;
4845 return !test;
4846}
4847
4848/* This helper checks whether given collection property itself is editable (we only currently
4849 * support a limited set of operations, insertion of new items, and re-ordering of those new items
4850 * exclusively). */
4852 PropertyRNA *prop,
4853 bool *r_is_liboverride)
4854{
4855 ID *id = ptr->owner_id;
4856 if (id == nullptr) {
4857 *r_is_liboverride = false;
4858 return true;
4859 }
4860
4861 const bool is_liboverride = *r_is_liboverride = ID_IS_OVERRIDE_LIBRARY(id);
4862
4863 if (!is_liboverride) {
4864 /* We return True also for linked data, as it allows tricks like py scripts 'overriding' data
4865 * of those. */
4866 return true;
4867 }
4868
4869 if (!RNA_property_overridable_get(ptr, prop)) {
4870 return false;
4871 }
4872
4873 if (prop->magic != RNA_MAGIC || (prop->flag & PROP_IDPROPERTY) == 0) {
4874 /* Insertion and such not supported for pure IDProperties for now, nor for pure RNA/DNA ones.
4875 */
4876 return false;
4877 }
4878 if ((prop->flag_override & PROPOVERRIDE_LIBRARY_INSERTION) == 0) {
4879 return false;
4880 }
4881
4882 /* No more checks to do, this collections is overridable. */
4883 return true;
4884}
4885
4887{
4888 IDProperty *idprop;
4889 // CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
4890
4892
4893 bool is_liboverride;
4894 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
4895 if (r_ptr) {
4896 *r_ptr = {};
4897 }
4898 return;
4899 }
4900
4901 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4902 IDProperty *item;
4903
4905 if (is_liboverride) {
4907 }
4908 IDP_AppendArray(idprop, item);
4909 /* IDP_AppendArray does a shallow copy (memcpy), only free memory. */
4910 // IDP_FreePropertyContent(item);
4911 MEM_freeN(item);
4912 rna_idproperty_touch(idprop);
4913 }
4914 else if (prop->flag & PROP_IDPROPERTY) {
4915 IDProperty *group, *item;
4916
4917 group = RNA_struct_system_idprops(ptr, true);
4918 if (group) {
4919 idprop = IDP_NewIDPArray(prop->identifier);
4920 IDP_AddToGroup(group, idprop);
4921
4923 if (is_liboverride) {
4925 }
4926 IDP_AppendArray(idprop, item);
4927 /* #IDP_AppendArray does a shallow copy (memcpy), only free memory. */
4928 // IDP_FreePropertyContent(item);
4929 MEM_freeN(item);
4930 }
4931 }
4932
4933 if (r_ptr) {
4934 if (idprop) {
4936
4938 *ptr, cprop->item_type, IDP_GetIndexArray(idprop, idprop->len - 1), *r_ptr);
4939 }
4940 else {
4941 *r_ptr = {};
4942 }
4943 }
4944}
4945
4947{
4948 IDProperty *idprop;
4949 // CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
4950
4952
4953 bool is_liboverride;
4954 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
4955 return false;
4956 }
4957
4958 if ((idprop = rna_idproperty_check(&prop, ptr))) {
4959 IDProperty tmp, *array;
4960 int len;
4961
4962 len = idprop->len;
4963 array = IDP_property_array_get(idprop);
4964
4965 if (key >= 0 && key < len) {
4966 if (is_liboverride && (array[key].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) == 0) {
4967 /* We can only remove items that we actually inserted in the local override. */
4968 return false;
4969 }
4970
4971 if (key + 1 < len) {
4972 /* move element to be removed to the back */
4973 memcpy(&tmp, &array[key], sizeof(IDProperty));
4974 memmove(array + key, array + key + 1, sizeof(IDProperty) * (len - (key + 1)));
4975 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
4976 }
4977
4978 IDP_ResizeIDPArray(idprop, len - 1);
4979 }
4980
4981 return true;
4982 }
4983 if (prop->flag & PROP_IDPROPERTY) {
4984 return true;
4985 }
4986
4987 return false;
4988}
4989
4991{
4992 IDProperty *idprop;
4993
4995
4996 bool is_liboverride;
4997 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
4998 return false;
4999 }
5000
5001 if ((idprop = rna_idproperty_check(&prop, ptr))) {
5002 IDProperty tmp, *array;
5003 int len;
5004
5005 len = idprop->len;
5006 array = IDP_property_array_get(idprop);
5007
5008 if (key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
5009 if (is_liboverride && (array[key].flag & IDP_FLAG_OVERRIDELIBRARY_LOCAL) == 0) {
5010 /* We can only move items that we actually inserted in the local override. */
5011 return false;
5012 }
5013
5014 memcpy(&tmp, &array[key], sizeof(IDProperty));
5015 if (pos < key) {
5016 memmove(array + pos + 1, array + pos, sizeof(IDProperty) * (key - pos));
5017 }
5018 else {
5019 memmove(array + key, array + key + 1, sizeof(IDProperty) * (pos - key));
5020 }
5021 memcpy(&array[pos], &tmp, sizeof(IDProperty));
5022 }
5023
5024 return true;
5025 }
5026 if (prop->flag & PROP_IDPROPERTY) {
5027 return true;
5028 }
5029
5030 return false;
5031}
5032
5034{
5035 IDProperty *idprop;
5036
5038
5039 bool is_liboverride;
5040 if (!property_collection_liboverride_editable(ptr, prop, &is_liboverride)) {
5041 return;
5042 }
5043
5044 if ((idprop = rna_idproperty_check(&prop, ptr))) {
5045 if (is_liboverride) {
5046 /* We can only move items that we actually inserted in the local override. */
5047 int len = idprop->len;
5048 IDProperty tmp, *array = IDP_property_array_get(idprop);
5049 for (int i = 0; i < len; i++) {
5051 memcpy(&tmp, &array[i], sizeof(IDProperty));
5052 memmove(array + i, array + i + 1, sizeof(IDProperty) * (len - (i + 1)));
5053 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
5054 IDP_ResizeIDPArray(idprop, --len);
5055 i--;
5056 }
5057 }
5058 }
5059 else {
5060 IDP_ResizeIDPArray(idprop, 0);
5061 }
5062 rna_idproperty_touch(idprop);
5063 }
5064}
5065
5067 PropertyRNA *prop,
5068 const PointerRNA *t_ptr)
5069{
5071 int index = 0;
5072
5074
5075 RNA_property_collection_begin(ptr, prop, &iter);
5076 for (index = 0; iter.valid; RNA_property_collection_next(&iter), index++) {
5077 if (iter.ptr.data == t_ptr->data) {
5078 break;
5079 }
5080 }
5082
5083 /* did we find it? */
5084 if (iter.valid) {
5085 return index;
5086 }
5087 return -1;
5088}
5089
5096
5103
5110
5116
5118 PropertyRNA *prop,
5119 int key,
5120 PointerRNA *r_ptr)
5121{
5123
5125
5126 if (cprop->lookupint) {
5127 /* we have a callback defined, use it */
5128 return cprop->lookupint(ptr, key, r_ptr);
5129 }
5130 /* no callback defined, just iterate and find the nth item */
5132 int i;
5133
5134 RNA_property_collection_begin(ptr, prop, &iter);
5135 for (i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
5136 if (i == key) {
5137 *r_ptr = iter.ptr;
5138 break;
5139 }
5140 }
5142
5143 if (!iter.valid) {
5144 *r_ptr = {};
5145 }
5146
5147 return iter.valid;
5148}
5149
5151 PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr, int *r_index)
5152{
5154
5156
5157 if (!key) {
5158 *r_index = -1;
5159 *r_ptr = PointerRNA_NULL;
5160 return false;
5161 }
5162
5163 if (cprop->lookupstring) {
5164 /* we have a callback defined, use it */
5165 return cprop->lookupstring(ptr, key, r_ptr);
5166 }
5167 /* no callback defined, compare with name properties if they exist */
5169 PropertyRNA *nameprop;
5170 char name_buf[256], *name;
5171 bool found = false;
5172 int keylen = strlen(key);
5173 int namelen;
5174 int index = 0;
5175
5176 RNA_property_collection_begin(ptr, prop, &iter);
5177 for (; iter.valid; RNA_property_collection_next(&iter), index++) {
5178 if (iter.ptr.data && iter.ptr.type->nameproperty) {
5179 nameprop = iter.ptr.type->nameproperty;
5180
5182 &iter.ptr, nameprop, name_buf, sizeof(name_buf), &namelen);
5183
5184 if ((keylen == namelen) && STREQ(name, key)) {
5185 *r_ptr = iter.ptr;
5186 found = true;
5187 }
5188
5189 if (name != name_buf) {
5190 MEM_freeN(name);
5191 }
5192
5193 if (found) {
5194 break;
5195 }
5196 }
5197 }
5199
5200 if (!iter.valid) {
5201 *r_ptr = {};
5202 *r_index = -1;
5203 }
5204 else {
5205 *r_index = index;
5206 }
5207
5208 return iter.valid;
5209}
5210
5212 PropertyRNA *prop,
5213 const char *key,
5214 PointerRNA *r_ptr)
5215{
5216 int index;
5217 return RNA_property_collection_lookup_string_index(ptr, prop, key, r_ptr, &index);
5218}
5219
5221 PropertyRNA *prop,
5222 const int key,
5223 const PointerRNA *assign_ptr)
5224{
5226
5228
5229 if (cprop->assignint) {
5230 /* we have a callback defined, use it */
5231 return cprop->assignint(ptr, key, assign_ptr);
5232 }
5233
5234 return false;
5235}
5236
5238{
5240
5241 *r_ptr = *ptr;
5242 return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1 : 0);
5243}
5244
5246 PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, bool set, RawArray *array)
5247{
5249 ArrayIterator *internal;
5250 char *arrayp;
5251
5253
5254 if (!(prop->flag_internal & PROP_INTERN_RAW_ARRAY) ||
5256 {
5257 return 0;
5258 }
5259
5260 RNA_property_collection_begin(ptr, prop, &iter);
5261
5262 if (iter.valid) {
5263 /* get data from array iterator and item property */
5264 internal = &iter.internal.array;
5265 arrayp = (iter.valid) ? static_cast<char *>(iter.ptr.data) : nullptr;
5266
5267 if (internal->skip || (set && !RNA_property_editable(&iter.ptr, itemprop))) {
5268 /* we might skip some items, so it's not a proper array */
5270 return 0;
5271 }
5272
5273 array->array = arrayp + itemprop->rawoffset;
5274 array->stride = internal->itemsize;
5275 array->len = ((char *)internal->endptr - arrayp) / internal->itemsize;
5276 array->type = itemprop->rawtype;
5277 }
5278 else {
5279 memset(array, 0, sizeof(RawArray));
5280 }
5281
5283
5284 return 1;
5285}
5286
5287#define RAW_GET(dtype, var, raw, a) \
5288 { \
5289 switch (raw.type) { \
5290 case PROP_RAW_CHAR: \
5291 var = (dtype)((char *)raw.array)[a]; \
5292 break; \
5293 case PROP_RAW_INT8: \
5294 var = (dtype)((int8_t *)raw.array)[a]; \
5295 break; \
5296 case PROP_RAW_UINT8: \
5297 var = (dtype)((uint8_t *)raw.array)[a]; \
5298 break; \
5299 case PROP_RAW_SHORT: \
5300 var = (dtype)((short *)raw.array)[a]; \
5301 break; \
5302 case PROP_RAW_UINT16: \
5303 var = (dtype)((uint16_t *)raw.array)[a]; \
5304 break; \
5305 case PROP_RAW_INT: \
5306 var = (dtype)((int *)raw.array)[a]; \
5307 break; \
5308 case PROP_RAW_BOOLEAN: \
5309 var = (dtype)((bool *)raw.array)[a]; \
5310 break; \
5311 case PROP_RAW_FLOAT: \
5312 var = (dtype)((float *)raw.array)[a]; \
5313 break; \
5314 case PROP_RAW_DOUBLE: \
5315 var = (dtype)((double *)raw.array)[a]; \
5316 break; \
5317 case PROP_RAW_INT64: \
5318 var = (dtype)((int64_t *)raw.array)[a]; \
5319 break; \
5320 case PROP_RAW_UINT64: \
5321 var = (dtype)((uint64_t *)raw.array)[a]; \
5322 break; \
5323 default: \
5324 var = (dtype)0; \
5325 } \
5326 } \
5327 (void)0
5328
5329#define RAW_SET(dtype, raw, a, var) \
5330 { \
5331 switch (raw.type) { \
5332 case PROP_RAW_CHAR: \
5333 ((char *)raw.array)[a] = char(var); \
5334 break; \
5335 case PROP_RAW_INT8: \
5336 ((int8_t *)raw.array)[a] = int8_t(var); \
5337 break; \
5338 case PROP_RAW_UINT8: \
5339 ((uint8_t *)raw.array)[a] = uint8_t(var); \
5340 break; \
5341 case PROP_RAW_SHORT: \
5342 ((short *)raw.array)[a] = short(var); \
5343 break; \
5344 case PROP_RAW_UINT16: \
5345 ((uint16_t *)raw.array)[a] = uint16_t(var); \
5346 break; \
5347 case PROP_RAW_INT: \
5348 ((int *)raw.array)[a] = int(var); \
5349 break; \
5350 case PROP_RAW_BOOLEAN: \
5351 ((bool *)raw.array)[a] = bool(var); \
5352 break; \
5353 case PROP_RAW_FLOAT: \
5354 ((float *)raw.array)[a] = float(var); \
5355 break; \
5356 case PROP_RAW_DOUBLE: \
5357 ((double *)raw.array)[a] = double(var); \
5358 break; \
5359 case PROP_RAW_INT64: \
5360 ((int64_t *)raw.array)[a] = int64_t(var); \
5361 break; \
5362 case PROP_RAW_UINT64: \
5363 ((uint64_t *)raw.array)[a] = uint64_t(var); \
5364 break; \
5365 default: \
5366 break; \
5367 } \
5368 } \
5369 (void)0
5370
5372{
5373 switch (type) {
5374 case PROP_RAW_CHAR:
5375 return sizeof(char);
5376 case PROP_RAW_INT8:
5377 return sizeof(int8_t);
5378 case PROP_RAW_UINT8:
5379 return sizeof(uint8_t);
5380 case PROP_RAW_SHORT:
5381 return sizeof(short);
5382 case PROP_RAW_UINT16:
5383 return sizeof(uint16_t);
5384 case PROP_RAW_INT:
5385 return sizeof(int);
5386 case PROP_RAW_BOOLEAN:
5387 return sizeof(bool);
5388 case PROP_RAW_FLOAT:
5389 return sizeof(float);
5390 case PROP_RAW_DOUBLE:
5391 return sizeof(double);
5392 case PROP_RAW_INT64:
5393 return sizeof(int64_t);
5394 case PROP_RAW_UINT64:
5395 return sizeof(uint64_t);
5396 default:
5397 return 0;
5398 }
5399}
5400
5402{
5404 const int dim = RNA_property_array_dimension(ptr, prop, len);
5405 int size;
5406
5407 if (dim == 0) {
5408 return 0;
5409 }
5410
5411 for (size = 1, i = 0; i < dim; i++) {
5412 size *= len[i];
5413 }
5414
5415 return size;
5416}
5417
5418static int rna_raw_access(ReportList *reports,
5419 PointerRNA *ptr,
5420 PropertyRNA *prop,
5421 const char *propname,
5422 void *inarray,
5423 RawPropertyType intype,
5424 int inlen,
5425 int set)
5426{
5427 StructRNA *ptype;
5428 PropertyRNA *itemprop, *iprop;
5429 PropertyType itemtype = PropertyType(0);
5430 RawArray in;
5431 /* Actual array length. Will always be `0` for non-array properties. */
5432 int array_len = 0;
5433 /* Item length. Will always be `1` for non-array properties. */
5434 int item_len = 0;
5435 /* Whether the accessed property is an array or not. */
5436 bool is_array;
5437
5438 /* initialize in array, stride assumed 0 in following code */
5439 in.array = inarray;
5440 in.type = intype;
5441 in.len = inlen;
5442 in.stride = 0;
5443
5444 ptype = RNA_property_pointer_type(ptr, prop);
5445
5446 /* try to get item property pointer */
5447 PointerRNA itemptr_base = RNA_pointer_create_discrete(nullptr, ptype, nullptr);
5448 itemprop = RNA_struct_find_property(&itemptr_base, propname);
5449
5450 if (itemprop) {
5451 /* we have item property pointer */
5452 RawArray out;
5453
5454 /* check type */
5455 itemtype = RNA_property_type(itemprop);
5456 is_array = RNA_property_array_check(itemprop);
5457
5458 if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
5459 BKE_report(reports, RPT_ERROR, "Only boolean, int, float, and enum properties supported");
5460 return 0;
5461 }
5462
5463 /* check item array */
5464 array_len = RNA_property_array_length(&itemptr_base, itemprop);
5465 item_len = is_array ? array_len : 1;
5466
5467 /* dynamic array? need to get length per item */
5468 if (itemprop->getlength) {
5469 itemprop = nullptr;
5470 }
5471 /* try to access as raw array */
5472 else if (RNA_property_collection_raw_array(ptr, prop, itemprop, set, &out)) {
5473 if (in.len != item_len * out.len) {
5474 BKE_reportf(reports,
5475 RPT_ERROR,
5476 "Array length mismatch (expected %d, got %d)",
5477 out.len * item_len,
5478 in.len);
5479 return 0;
5480 }
5481
5482 /* matching raw types */
5483 if (out.type == in.type) {
5484 void *inp = in.array;
5485 void *outp = out.array;
5486 size_t size;
5487
5488 size = RNA_raw_type_sizeof(out.type) * item_len;
5489
5490 if (size == out.stride) {
5491 /* The property is stored contiguously so the entire array can be copied at once. */
5492 if (set) {
5493 memcpy(outp, inp, size * out.len);
5494 }
5495 else {
5496 memcpy(inp, outp, size * out.len);
5497 }
5498 }
5499 else {
5500 for (int a = 0; a < out.len; a++) {
5501 if (set) {
5502 memcpy(outp, inp, size);
5503 }
5504 else {
5505 memcpy(inp, outp, size);
5506 }
5507
5508 inp = (char *)inp + size;
5509 outp = (char *)outp + out.stride;
5510 }
5511 }
5512
5513 return 1;
5514 }
5515
5516 /* Could also be faster with non-matching types,
5517 * for now we just do slower loop. */
5518 }
5519 BLI_assert_msg(array_len == 0 || itemtype != PROP_ENUM,
5520 "Enum array properties should not exist");
5521 }
5522
5523 {
5524 void *tmparray = nullptr;
5525 int tmplen = 0;
5526 int err = 0, j, a = 0;
5527 int needconv = 1;
5528
5529 if (((itemtype == PROP_INT) && (in.type == PROP_RAW_INT)) ||
5530 ((itemtype == PROP_BOOLEAN) && (in.type == PROP_RAW_BOOLEAN)) ||
5531 ((itemtype == PROP_FLOAT) && (in.type == PROP_RAW_FLOAT)))
5532 {
5533 /* avoid creating temporary buffer if the data type match */
5534 needconv = 0;
5535 }
5536 /* no item property pointer, can still be id property, or
5537 * property of a type derived from the collection pointer type */
5538 RNA_PROP_BEGIN (ptr, itemptr, prop) {
5539 if (itemptr.data) {
5540 if (itemprop) {
5541 /* we got the property already */
5542 iprop = itemprop;
5543 }
5544 else {
5545 /* not yet, look it up and verify if it is valid */
5546 iprop = RNA_struct_find_property(&itemptr, propname);
5547
5548 if (iprop) {
5549 is_array = RNA_property_array_check(iprop);
5550 array_len = rna_property_array_length_all_dimensions(&itemptr, iprop);
5551 item_len = is_array ? array_len : 1;
5552 itemtype = RNA_property_type(iprop);
5553 }
5554 else {
5555 BKE_reportf(reports, RPT_ERROR, "Property named '%s' not found", propname);
5556 err = 1;
5557 break;
5558 }
5559
5560 if (!ELEM(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
5561 BKE_report(
5562 reports, RPT_ERROR, "Only boolean, int, float and enum properties supported");
5563 err = 1;
5564 break;
5565 }
5566 BLI_assert_msg(array_len == 0 || itemtype != PROP_ENUM,
5567 "Enum array properties should not exist");
5568 }
5569
5570 /* editable check */
5571 if (!set || RNA_property_editable(&itemptr, iprop)) {
5572 if (a + item_len > in.len) {
5574 reports, RPT_ERROR, "Array length mismatch (got %d, expected more)", in.len);
5575 err = 1;
5576 break;
5577 }
5578
5579 if (array_len == 0) {
5580 /* handle conversions */
5581 if (set) {
5582 switch (itemtype) {
5583 case PROP_BOOLEAN: {
5584 int b;
5585 RAW_GET(bool, b, in, a);
5586 RNA_property_boolean_set(&itemptr, iprop, b);
5587 break;
5588 }
5589 case PROP_INT: {
5590 int i;
5591 RAW_GET(int, i, in, a);
5592 RNA_property_int_set(&itemptr, iprop, i);
5593 break;
5594 }
5595 case PROP_FLOAT: {
5596 float f;
5597 RAW_GET(float, f, in, a);
5598 RNA_property_float_set(&itemptr, iprop, f);
5599 break;
5600 }
5601 case PROP_ENUM: {
5602 int i;
5603 RAW_GET(int, i, in, a);
5604 RNA_property_enum_set(&itemptr, iprop, i);
5605 break;
5606 }
5607 default:
5609 break;
5610 }
5611 }
5612 else {
5613 switch (itemtype) {
5614 case PROP_BOOLEAN: {
5615 int b = RNA_property_boolean_get(&itemptr, iprop);
5616 RAW_SET(bool, in, a, b);
5617 break;
5618 }
5619 case PROP_INT: {
5620 int i = RNA_property_int_get(&itemptr, iprop);
5621 RAW_SET(int, in, a, i);
5622 break;
5623 }
5624 case PROP_FLOAT: {
5625 float f = RNA_property_float_get(&itemptr, iprop);
5626 RAW_SET(float, in, a, f);
5627 break;
5628 }
5629 case PROP_ENUM: {
5630 int i = RNA_property_enum_get(&itemptr, iprop);
5631 RAW_SET(int, in, a, i);
5632 break;
5633 }
5634 default:
5636 break;
5637 }
5638 }
5639 a++;
5640 }
5641 else if (needconv == 1) {
5642 /* allocate temporary array if needed */
5643 if (tmparray && tmplen != array_len) {
5644 MEM_freeN(tmparray);
5645 tmparray = nullptr;
5646 }
5647 if (!tmparray) {
5648 tmparray = MEM_calloc_arrayN<float>(array_len, "RNA tmparray");
5649 tmplen = array_len;
5650 }
5651
5652 /* handle conversions */
5653 if (set) {
5654 switch (itemtype) {
5655 case PROP_BOOLEAN: {
5656 bool *array = static_cast<bool *>(tmparray);
5657 for (j = 0; j < array_len; j++, a++) {
5658 RAW_GET(bool, array[j], in, a);
5659 }
5660 RNA_property_boolean_set_array(&itemptr, iprop, array);
5661 break;
5662 }
5663 case PROP_INT: {
5664 int *array = static_cast<int *>(tmparray);
5665 for (j = 0; j < array_len; j++, a++) {
5666 RAW_GET(int, array[j], in, a);
5667 }
5668 RNA_property_int_set_array(&itemptr, iprop, array);
5669 break;
5670 }
5671 case PROP_FLOAT: {
5672 float *array = static_cast<float *>(tmparray);
5673 for (j = 0; j < array_len; j++, a++) {
5674 RAW_GET(float, array[j], in, a);
5675 }
5676 RNA_property_float_set_array(&itemptr, iprop, array);
5677 break;
5678 }
5679 default:
5681 break;
5682 }
5683 }
5684 else {
5685 switch (itemtype) {
5686 case PROP_BOOLEAN: {
5687 bool *array = static_cast<bool *>(tmparray);
5688 RNA_property_boolean_get_array(&itemptr, iprop, array);
5689 for (j = 0; j < array_len; j++, a++) {
5690 RAW_SET(int, in, a, ((bool *)tmparray)[j]);
5691 }
5692 break;
5693 }
5694 case PROP_INT: {
5695 int *array = static_cast<int *>(tmparray);
5696 RNA_property_int_get_array(&itemptr, iprop, array);
5697 for (j = 0; j < array_len; j++, a++) {
5698 RAW_SET(int, in, a, array[j]);
5699 }
5700 break;
5701 }
5702 case PROP_FLOAT: {
5703 float *array = static_cast<float *>(tmparray);
5704 RNA_property_float_get_array(&itemptr, iprop, array);
5705 for (j = 0; j < array_len; j++, a++) {
5706 RAW_SET(float, in, a, array[j]);
5707 }
5708 break;
5709 }
5710 default:
5712 break;
5713 }
5714 }
5715 }
5716 else {
5717 if (set) {
5718 switch (itemtype) {
5719 case PROP_BOOLEAN: {
5720 RNA_property_boolean_set_array(&itemptr, iprop, &((bool *)in.array)[a]);
5721 a += array_len;
5722 break;
5723 }
5724 case PROP_INT: {
5725 RNA_property_int_set_array(&itemptr, iprop, &((int *)in.array)[a]);
5726 a += array_len;
5727 break;
5728 }
5729 case PROP_FLOAT: {
5730 RNA_property_float_set_array(&itemptr, iprop, &((float *)in.array)[a]);
5731 a += array_len;
5732 break;
5733 }
5734 default:
5736 break;
5737 }
5738 }
5739 else {
5740 switch (itemtype) {
5741 case PROP_BOOLEAN: {
5742 RNA_property_boolean_get_array(&itemptr, iprop, &((bool *)in.array)[a]);
5743 a += array_len;
5744 break;
5745 }
5746 case PROP_INT: {
5747 RNA_property_int_get_array(&itemptr, iprop, &((int *)in.array)[a]);
5748 a += array_len;
5749 break;
5750 }
5751 case PROP_FLOAT: {
5752 RNA_property_float_get_array(&itemptr, iprop, &((float *)in.array)[a]);
5753 a += array_len;
5754 break;
5755 }
5756 default:
5758 break;
5759 }
5760 }
5761 }
5762 }
5763 }
5764 }
5766
5767 if (tmparray) {
5768 MEM_freeN(tmparray);
5769 }
5770
5771 return !err;
5772 }
5773}
5774
5776{
5777 if (prop->rawtype == PROP_RAW_UNSET) {
5778 /* this property has no raw access,
5779 * yet we try to provide a raw type to help building the array. */
5780 switch (prop->type) {
5781 case PROP_BOOLEAN:
5782 return PROP_RAW_BOOLEAN;
5783 case PROP_INT:
5784 return PROP_RAW_INT;
5785 case PROP_FLOAT:
5786 return PROP_RAW_FLOAT;
5787 case PROP_ENUM:
5788 return PROP_RAW_INT;
5789 default:
5790 break;
5791 }
5792 }
5793 return prop->rawtype;
5794}
5795
5797 PointerRNA *ptr,
5798 PropertyRNA *prop,
5799 const char *propname,
5800 void *array,
5801 RawPropertyType type,
5802 int len)
5803{
5804 return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0);
5805}
5806
5808 PointerRNA *ptr,
5809 PropertyRNA *prop,
5810 const char *propname,
5811 void *array,
5812 RawPropertyType type,
5813 int len)
5814{
5815 return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1);
5816}
5817
5818/* Standard iterator functions */
5819
5821 PointerRNA *ptr,
5822 ListBase *lb,
5823 IteratorSkipFunc skip)
5824{
5825 iter->parent = *ptr;
5826
5827 ListBaseIterator *internal = &iter->internal.listbase;
5828
5829 internal->link = (lb) ? static_cast<Link *>(lb->first) : nullptr;
5830 internal->skip = skip;
5831
5832 iter->valid = (internal->link != nullptr);
5833
5834 if (skip && iter->valid && skip(iter, internal->link)) {
5836 }
5837}
5838
5840{
5841 ListBaseIterator *internal = &iter->internal.listbase;
5842
5843 if (internal->skip) {
5844 do {
5845 internal->link = internal->link->next;
5846 iter->valid = (internal->link != nullptr);
5847 } while (iter->valid && internal->skip(iter, internal->link));
5848 }
5849 else {
5850 internal->link = internal->link->next;
5851 iter->valid = (internal->link != nullptr);
5852 }
5853}
5854
5856{
5857 ListBaseIterator *internal = &iter->internal.listbase;
5858
5859 return internal->link;
5860}
5861
5863
5865{
5866 void *data = BLI_findlink(lb, index);
5867 return RNA_pointer_create_with_parent(*ptr, type, data);
5868}
5869
5871 PointerRNA *ptr,
5872 void *data,
5873 size_t itemsize,
5875 bool free_ptr,
5876 IteratorSkipFunc skip)
5877{
5878 iter->parent = *ptr;
5879
5880 ArrayIterator *internal;
5881
5882 if (data == nullptr) {
5883 length = 0;
5884 }
5885 else if (length == 0) {
5886 data = nullptr;
5887 itemsize = 0;
5888 }
5889 else if (UNLIKELY(length < 0 || length > std::numeric_limits<uint64_t>::max() / itemsize)) {
5890 /* This path is never expected to execute. Assert and trace if it ever does. */
5892 data = nullptr;
5893 length = 0;
5894 }
5895
5896 internal = &iter->internal.array;
5897 internal->ptr = static_cast<char *>(data);
5898 internal->free_ptr = free_ptr ? data : nullptr;
5899 internal->endptr = ((char *)data) + itemsize * length;
5900 internal->itemsize = itemsize;
5901 internal->skip = skip;
5902 internal->length = length;
5903
5904 iter->valid = (internal->ptr != internal->endptr);
5905
5906 if (skip && iter->valid && skip(iter, internal->ptr)) {
5908 }
5909}
5910
5912{
5913 ArrayIterator *internal = &iter->internal.array;
5914
5915 if (internal->skip) {
5916 do {
5917 internal->ptr += internal->itemsize;
5918 iter->valid = (internal->ptr != internal->endptr);
5919 } while (iter->valid && internal->skip(iter, internal->ptr));
5920 }
5921 else {
5922 internal->ptr += internal->itemsize;
5923 iter->valid = (internal->ptr != internal->endptr);
5924 }
5925}
5926
5928{
5929 ArrayIterator *internal = &iter->internal.array;
5930
5931 return internal->ptr;
5932}
5933
5935{
5936 ArrayIterator *internal = &iter->internal.array;
5937
5938 /* for ** arrays */
5939 return *(void **)(internal->ptr);
5940}
5941
5943{
5944 ArrayIterator *internal = &iter->internal.array;
5945
5946 MEM_SAFE_FREE(internal->free_ptr);
5947}
5948
5950 PointerRNA *ptr, StructRNA *type, void *data, size_t itemsize, int64_t length, int64_t index)
5951{
5952 if (index < 0 || index >= length) {
5953 return PointerRNA_NULL;
5954 }
5955 if (UNLIKELY(index > std::numeric_limits<uint64_t>::max() / itemsize)) {
5956 /* This path is never expected to execute. Assert and trace if it ever does. */
5958 return PointerRNA_NULL;
5959 }
5960
5961 return RNA_pointer_create_with_parent(*ptr, type, ((char *)data) + itemsize * index);
5962}
5963
5964/* Quick name based property access */
5965
5967{
5969
5970 if (prop) {
5971 return RNA_property_boolean_get(ptr, prop);
5972 }
5973 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
5974 return false;
5975}
5976
5977void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
5978{
5980
5981 if (prop) {
5982 RNA_property_boolean_set(ptr, prop, value);
5983 }
5984 else {
5985 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
5986 }
5987}
5988
5989void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
5990{
5992
5993 if (prop) {
5994 RNA_property_boolean_get_array(ptr, prop, values);
5995 }
5996 else {
5997 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
5998 }
5999}
6000
6001void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const bool *values)
6002{
6004
6005 if (prop) {
6006 RNA_property_boolean_set_array(ptr, prop, values);
6007 }
6008 else {
6009 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6010 }
6011}
6012
6013int RNA_int_get(PointerRNA *ptr, const char *name)
6014{
6016
6017 if (prop) {
6018 return RNA_property_int_get(ptr, prop);
6019 }
6020 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6021 return 0;
6022}
6023
6024void RNA_int_set(PointerRNA *ptr, const char *name, int value)
6025{
6027
6028 if (prop) {
6029 RNA_property_int_set(ptr, prop, value);
6030 }
6031 else {
6032 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6033 }
6034}
6035
6036void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
6037{
6039
6040 if (prop) {
6041 RNA_property_int_get_array(ptr, prop, values);
6042 }
6043 else {
6044 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6045 }
6046}
6047
6048void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
6049{
6051
6052 if (prop) {
6053 RNA_property_int_set_array(ptr, prop, values);
6054 }
6055 else {
6056 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6057 }
6058}
6059
6060float RNA_float_get(PointerRNA *ptr, const char *name)
6061{
6063
6064 if (prop) {
6065 return RNA_property_float_get(ptr, prop);
6066 }
6067 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6068 return 0;
6069}
6070
6071void RNA_float_set(PointerRNA *ptr, const char *name, float value)
6072{
6074
6075 if (prop) {
6076 RNA_property_float_set(ptr, prop, value);
6077 }
6078 else {
6079 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6080 }
6081}
6082
6083void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
6084{
6086
6087 if (prop) {
6088 RNA_property_float_get_array(ptr, prop, values);
6089 }
6090 else {
6091 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6092 }
6093}
6094
6095void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
6096{
6098
6099 if (prop) {
6100 RNA_property_float_set_array(ptr, prop, values);
6101 }
6102 else {
6103 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6104 }
6105}
6106
6108{
6110
6111 if (prop) {
6112 return RNA_property_enum_get(ptr, prop);
6113 }
6114 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6115 return 0;
6116}
6117
6118void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
6119{
6121
6122 if (prop) {
6123 RNA_property_enum_set(ptr, prop, value);
6124 }
6125 else {
6126 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6127 }
6128}
6129
6130void RNA_enum_set_identifier(bContext *C, PointerRNA *ptr, const char *name, const char *id)
6131{
6133
6134 if (prop) {
6135 int value;
6136 if (RNA_property_enum_value(C, ptr, prop, id, &value)) {
6137 RNA_property_enum_set(ptr, prop, value);
6138 }
6139 else {
6140 printf("%s: %s.%s has no enum id '%s'.\n", __func__, ptr->type->identifier, name, id);
6141 }
6142 }
6143 else {
6144 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6145 }
6146}
6147
6148bool RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname)
6149{
6151 const EnumPropertyItem *item;
6152 bool free;
6153
6154 if (prop) {
6155 int i;
6156 bool cmp = false;
6157
6158 RNA_property_enum_items(C, ptr, prop, &item, nullptr, &free);
6159 i = RNA_enum_from_identifier(item, enumname);
6160 if (i != -1) {
6161 cmp = (item[i].value == RNA_property_enum_get(ptr, prop));
6162 }
6163
6164 if (free) {
6165 MEM_freeN(item);
6166 }
6167
6168 if (i != -1) {
6169 return cmp;
6170 }
6171
6172 printf("%s: %s.%s item %s not found.\n", __func__, ptr->type->identifier, name, enumname);
6173 return false;
6174 }
6175 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6176 return false;
6177}
6178
6179bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
6180{
6181 const int i = RNA_enum_from_identifier(item, identifier);
6182 if (i != -1) {
6183 *r_value = item[i].value;
6184 return true;
6185 }
6186 return false;
6187}
6188
6189bool RNA_enum_id_from_value(const EnumPropertyItem *item, int value, const char **r_identifier)
6190{
6191 const int i = RNA_enum_from_value(item, value);
6192 if (i != -1) {
6193 *r_identifier = item[i].identifier;
6194 return true;
6195 }
6196 return false;
6197}
6198
6199bool RNA_enum_icon_from_value(const EnumPropertyItem *item, int value, int *r_icon)
6200{
6201 const int i = RNA_enum_from_value(item, value);
6202 if (i != -1) {
6203 *r_icon = item[i].icon;
6204 return true;
6205 }
6206 return false;
6207}
6208
6209bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name)
6210{
6211 const int i = RNA_enum_from_value(item, value);
6212 if (i != -1) {
6213 *r_name = item[i].name;
6214 return true;
6215 }
6216 return false;
6217}
6218
6219std::string RNA_string_get(PointerRNA *ptr, const char *name)
6220{
6222 if (!prop) {
6223 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6224 return {};
6225 }
6226 return RNA_property_string_get(ptr, prop);
6227}
6228
6229void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
6230{
6232
6233 if (prop) {
6234 RNA_property_string_get(ptr, prop, value);
6235 }
6236 else {
6237 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6238 value[0] = '\0';
6239 }
6240}
6241
6243 PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
6244{
6246
6247 if (prop) {
6248 return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen, r_len);
6249 }
6250 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6251 if (r_len != nullptr) {
6252 *r_len = 0;
6253 }
6254 return nullptr;
6255}
6256
6258{
6260
6261 if (prop) {
6262 return RNA_property_string_length(ptr, prop);
6263 }
6264 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6265 return 0;
6266}
6267
6268void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
6269{
6271
6272 if (prop) {
6273 RNA_property_string_set(ptr, prop, value);
6274 }
6275 else {
6276 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6277 }
6278}
6279
6281{
6283
6284 if (prop) {
6285 return RNA_property_pointer_get(ptr, prop);
6286 }
6287 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6288
6289 return PointerRNA_NULL;
6290}
6291
6292void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
6293{
6295
6296 if (prop) {
6297 RNA_property_pointer_set(ptr, prop, ptr_value, nullptr);
6298 }
6299 else {
6300 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6301 }
6302}
6303
6305{
6307
6308 if (prop) {
6310 }
6311 else {
6312 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6313 }
6314}
6315
6317{
6319
6320 if (prop) {
6322 }
6323 else {
6324 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6325 }
6326}
6327
6328void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
6329{
6331
6332 if (prop) {
6333 RNA_property_collection_add(ptr, prop, r_value);
6334 }
6335 else {
6336 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6337 }
6338}
6339
6341{
6343
6344 if (prop) {
6346 }
6347 else {
6348 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6349 }
6350}
6351
6353{
6355
6356 if (prop) {
6357 return RNA_property_collection_length(ptr, prop);
6358 }
6359 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6360 return 0;
6361}
6362
6364{
6366
6367 if (prop) {
6369 }
6370 printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6371 return false;
6372}
6373
6375{
6376 prop = rna_ensure_property(prop);
6377 if (prop->flag & PROP_IDPROPERTY) {
6379 return ((idprop != nullptr) && (use_ghost == false || !(idprop->flag & IDP_FLAG_GHOST)));
6380 }
6381 return true;
6382}
6383
6385{
6386 prop = rna_ensure_property(prop);
6387 if (prop->flag & PROP_IDPROPERTY) {
6389 return ((idprop != nullptr) && !(idprop->flag & IDP_FLAG_GHOST));
6390 }
6391 return true;
6392}
6393
6395{
6396 prop = rna_ensure_property(prop);
6397 if (prop->flag & PROP_IDPROPERTY) {
6399 }
6400}
6401
6402bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
6403{
6404 PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
6405
6406 if (prop) {
6407 return RNA_property_is_set_ex(ptr, prop, use_ghost);
6408 }
6409 /* python raises an error */
6410 // printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6411 return false;
6412}
6413
6414bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
6415{
6416 PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
6417
6418 if (prop) {
6419 return RNA_property_is_set(ptr, prop);
6420 }
6421 /* python raises an error */
6422 // printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name);
6423 return false;
6424}
6425
6426void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
6427{
6428 PropertyRNA *prop = RNA_struct_find_property(ptr, identifier);
6429
6430 if (prop) {
6431 RNA_property_unset(ptr, prop);
6432 }
6433}
6434
6436{
6437 return (prop->magic != RNA_MAGIC);
6438}
6439
6441{
6442 const int flag = RNA_property_flag(prop);
6443 if (RNA_property_type(prop) == PROP_STRING) {
6444 return (flag & PROP_NEVER_UNLINK) == 0;
6445 }
6446 return (flag & (PROP_NEVER_UNLINK | PROP_NEVER_NULL)) == 0;
6447}
6448
6450{
6451 std::stringstream ss;
6452
6453 const char *propname;
6454 int first_time = 1;
6455
6456 ss << '{';
6457
6458 RNA_STRUCT_BEGIN (ptr, prop) {
6459 propname = RNA_property_identifier(prop);
6460
6461 if (STREQ(propname, "rna_type")) {
6462 continue;
6463 }
6464
6465 if (first_time == 0) {
6466 ss << ", ";
6467 }
6468 first_time = 0;
6469
6470 const std::string str = RNA_property_as_string(C, ptr, prop, -1, INT_MAX);
6471 ss << fmt::format("\"{}\":{}", propname, str);
6472 }
6474
6475 ss << '}';
6476
6477 return ss.str();
6478}
6479
6480static std::optional<std::string> rna_pointer_as_string__bldata(PointerRNA *ptr)
6481{
6482 if (ptr->type == nullptr || ptr->owner_id == nullptr) {
6483 return "None";
6484 }
6485 if (RNA_struct_is_ID(ptr->type)) {
6486 return RNA_path_full_ID_py(ptr->owner_id);
6487 }
6489}
6490
6491std::optional<std::string> RNA_pointer_as_string(bContext *C,
6492 PointerRNA *ptr,
6493 PropertyRNA *prop_ptr,
6494 PointerRNA *ptr_prop)
6495{
6496 IDProperty *prop;
6497 if (ptr_prop->data == nullptr) {
6498 return "None";
6499 }
6500 if ((prop = rna_idproperty_check(&prop_ptr, ptr)) && prop->type != IDP_ID) {
6501 return RNA_pointer_as_string_id(C, ptr_prop);
6502 }
6503 return rna_pointer_as_string__bldata(ptr_prop);
6504}
6505
6507 PointerRNA *ptr,
6508 const bool as_function,
6509 const bool all_args,
6510 const bool nested_args,
6511 const int max_prop_length,
6512 PropertyRNA *iterprop)
6513{
6514 const char *arg_name = nullptr;
6515
6516 PropertyRNA *prop;
6517
6518 std::stringstream ss;
6519
6520 bool first_iter = true;
6521 int flag, flag_parameter;
6522
6523 RNA_PROP_BEGIN (ptr, propptr, iterprop) {
6524 prop = static_cast<PropertyRNA *>(propptr.data);
6525
6526 flag = RNA_property_flag(prop);
6527 flag_parameter = RNA_parameter_flag(prop);
6528
6529 if (as_function && (flag_parameter & PARM_OUTPUT)) {
6530 continue;
6531 }
6532
6533 arg_name = RNA_property_identifier(prop);
6534
6535 if (STREQ(arg_name, "rna_type")) {
6536 continue;
6537 }
6538
6539 if ((nested_args == false) && (RNA_property_type(prop) == PROP_POINTER)) {
6540 continue;
6541 }
6542
6543 if (as_function && (prop->flag_parameter & PARM_REQUIRED)) {
6544 /* required args don't have useful defaults */
6545 ss << fmt::format(fmt::runtime(first_iter ? "{}" : ", {}"), arg_name);
6546 first_iter = false;
6547 }
6548 else {
6549 bool ok = true;
6550
6551 if (all_args == true) {
6552 /* pass */
6553 }
6554 else if (RNA_struct_system_idprops_check(ptr->type)) {
6555 ok = RNA_property_is_set(ptr, prop);
6556 }
6557
6558 if (ok) {
6559 std::string buf;
6560 if (as_function && RNA_property_type(prop) == PROP_POINTER) {
6561 /* don't expand pointers for functions */
6562 if (flag & PROP_NEVER_NULL) {
6563 /* we can't really do the right thing here. arg=arg?, hrmf! */
6564 buf = arg_name;
6565 }
6566 else {
6567 buf = "None";
6568 }
6569 }
6570 else {
6571 buf = RNA_property_as_string(C, ptr, prop, -1, max_prop_length);
6572 }
6573
6574 ss << fmt::format(fmt::runtime(first_iter ? "{}={}" : ", {}={}"), arg_name, buf);
6575 first_iter = false;
6576 }
6577 }
6578 }
6580
6581 return ss.str();
6582}
6583
6585 PointerRNA *ptr,
6586 const bool as_function,
6587 const bool all_args,
6588 const bool nested_args,
6589 const int max_prop_length)
6590{
6591 PropertyRNA *iterprop;
6592
6593 iterprop = RNA_struct_iterator_property(ptr->type);
6594
6596 C, ptr, as_function, all_args, nested_args, max_prop_length, iterprop);
6597}
6598
6600 FunctionRNA *func,
6601 const bool as_function,
6602 const bool all_args,
6603 const int max_prop_length)
6604{
6605 PointerRNA funcptr = RNA_pointer_create_discrete(nullptr, &RNA_Function, func);
6606
6607 PropertyRNA *iterprop = RNA_struct_find_property(&funcptr, "parameters");
6608
6610
6612 C, &funcptr, as_function, all_args, true, max_prop_length, iterprop);
6613}
6614
6615static const char *bool_as_py_string(const int var)
6616{
6617 return var ? "True" : "False";
6618}
6619
6621 int type, int len, PointerRNA *ptr, PropertyRNA *prop, void **r_buf_end)
6622{
6623 switch (type) {
6624 case PROP_BOOLEAN: {
6625 bool *buf = MEM_malloc_arrayN<bool>(size_t(len), __func__);
6627 *r_buf_end = buf + len;
6628 return buf;
6629 }
6630 case PROP_INT: {
6631 int *buf = MEM_malloc_arrayN<int>(size_t(len), __func__);
6632 RNA_property_int_get_array(ptr, prop, buf);
6633 *r_buf_end = buf + len;
6634 return buf;
6635 }
6636 case PROP_FLOAT: {
6637 float *buf = MEM_malloc_arrayN<float>(size_t(len), __func__);
6639 *r_buf_end = buf + len;
6640 return buf;
6641 }
6642 default:
6644 return nullptr;
6645 }
6646}
6647
6648static void rna_array_as_string_elem(int type, void **buf_p, int len, std::stringstream &ss)
6649{
6650 /* This will print a comma separated string of the array elements from
6651 * buf start to len. We will add a comma if len == 1 to preserve tuples. */
6652 const int end = len - 1;
6653 switch (type) {
6654 case PROP_BOOLEAN: {
6655 bool *buf = static_cast<bool *>(*buf_p);
6656 for (int i = 0; i < len; i++, buf++) {
6657 ss << fmt::format(fmt::runtime((i < end || !end) ? "{}, " : "{}"),
6658 bool_as_py_string(*buf));
6659 }
6660 *buf_p = buf;
6661 break;
6662 }
6663 case PROP_INT: {
6664 int *buf = static_cast<int *>(*buf_p);
6665 for (int i = 0; i < len; i++, buf++) {
6666 ss << fmt::format(fmt::runtime((i < end || !end) ? "{}, " : "{}"), *buf);
6667 }
6668 *buf_p = buf;
6669 break;
6670 }
6671 case PROP_FLOAT: {
6672 float *buf = static_cast<float *>(*buf_p);
6673 for (int i = 0; i < len; i++, buf++) {
6674 ss << fmt::format(fmt::runtime((i < end || !end) ? "{:g}, " : "{:g}"), *buf);
6675 }
6676 *buf_p = buf;
6677 break;
6678 }
6679 default:
6681 }
6682}
6683
6685 int type, void **buf_p, int totdim, const int *dim_size, std::stringstream &ss)
6686{
6687 ss << '(';
6688 if (totdim > 1) {
6689 totdim--;
6690 const int end = dim_size[totdim] - 1;
6691 for (int i = 0; i <= end; i++) {
6692 rna_array_as_string_recursive(type, buf_p, totdim, dim_size, ss);
6693 if (i < end || !end) {
6694 ss << ", ";
6695 }
6696 }
6697 }
6698 else {
6699 rna_array_as_string_elem(type, buf_p, dim_size[0], ss);
6700 }
6701 ss << ')';
6702}
6703
6705 int type, int len, PointerRNA *ptr, PropertyRNA *prop, std::stringstream &ss)
6706{
6707 void *buf_end;
6708 void *buf = rna_array_as_string_alloc(type, len, ptr, prop, &buf_end);
6709 void *buf_step = buf;
6710 int totdim, dim_size[RNA_MAX_ARRAY_DIMENSION];
6711
6712 totdim = RNA_property_array_dimension(ptr, prop, dim_size);
6713
6714 rna_array_as_string_recursive(type, &buf_step, totdim, dim_size, ss);
6715 BLI_assert(buf_step == buf_end);
6716 MEM_freeN(buf);
6717}
6718
6720 bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length)
6721{
6722 int type = RNA_property_type(prop);
6723 int len = RNA_property_array_length(ptr, prop);
6724
6725 std::stringstream ss;
6726
6727 /* see if we can coerce into a python type - PropertyType */
6728 switch (type) {
6729 case PROP_BOOLEAN:
6730 if (len == 0) {
6732 }
6733 else {
6734 if (index != -1) {
6736 }
6737 else {
6738 rna_array_as_string(type, len, ptr, prop, ss);
6739 }
6740 }
6741 break;
6742 case PROP_INT:
6743 if (len == 0) {
6744 ss << RNA_property_int_get(ptr, prop);
6745 }
6746 else {
6747 if (index != -1) {
6748 ss << RNA_property_int_get_index(ptr, prop, index);
6749 }
6750 else {
6751 rna_array_as_string(type, len, ptr, prop, ss);
6752 }
6753 }
6754 break;
6755 case PROP_FLOAT:
6756 if (len == 0) {
6757 ss << fmt::format("{:g}", RNA_property_float_get(ptr, prop));
6758 }
6759 else {
6760 if (index != -1) {
6761 ss << fmt::format("{:g}", RNA_property_float_get_index(ptr, prop, index));
6762 }
6763 else {
6764 rna_array_as_string(type, len, ptr, prop, ss);
6765 }
6766 }
6767 break;
6768 case PROP_STRING: {
6769 char *buf_esc;
6770 char *buf;
6771 int length;
6772
6774 buf = MEM_malloc_arrayN<char>(size_t(length) + 1, "RNA_property_as_string");
6775 buf_esc = MEM_malloc_arrayN<char>(size_t(length) * 2 + 1, "RNA_property_as_string esc");
6776 RNA_property_string_get(ptr, prop, buf);
6777 BLI_str_escape(buf_esc, buf, length * 2 + 1);
6778 MEM_freeN(buf);
6779 ss << fmt::format("\"{}\"", buf_esc);
6780 MEM_freeN(buf_esc);
6781 break;
6782 }
6783 case PROP_ENUM: {
6784 /* string arrays don't exist */
6785 const char *identifier;
6786 int val = RNA_property_enum_get(ptr, prop);
6787
6788 if (RNA_property_flag(prop) & PROP_ENUM_FLAG) {
6789 /* represent as a python set */
6790 if (val) {
6791 const EnumPropertyItem *item_array;
6792 bool free;
6793
6794 ss << "{";
6795
6796 RNA_property_enum_items(C, ptr, prop, &item_array, nullptr, &free);
6797 if (item_array) {
6798 const EnumPropertyItem *item = item_array;
6799 bool is_first = true;
6800 for (; item->identifier; item++) {
6801 if (item->identifier[0] && item->value & val) {
6802 ss << fmt::format(fmt::runtime(is_first ? "'{}'" : ", '{}'"), item->identifier);
6803 is_first = false;
6804 }
6805 }
6806
6807 if (free) {
6808 MEM_freeN(item_array);
6809 }
6810 }
6811
6812 ss << "}";
6813 }
6814 else {
6815 /* annoying exception, don't confuse with dictionary syntax above: {} */
6816 ss << "set()";
6817 }
6818 }
6819 else if (RNA_property_enum_identifier(C, ptr, prop, val, &identifier)) {
6820 ss << fmt::format("'{}'", identifier);
6821 }
6822 else {
6823 return "'<UNKNOWN ENUM>'";
6824 }
6825 break;
6826 }
6827 case PROP_POINTER: {
6829 ss << RNA_pointer_as_string(C, ptr, prop, &tptr).value_or("");
6830 break;
6831 }
6832 case PROP_COLLECTION: {
6833 int i = 0;
6834 CollectionPropertyIterator collect_iter;
6835 ss << "[";
6836
6837 for (RNA_property_collection_begin(ptr, prop, &collect_iter);
6838 (i < max_prop_length) && collect_iter.valid;
6839 RNA_property_collection_next(&collect_iter), i++)
6840 {
6841 PointerRNA itemptr = collect_iter.ptr;
6842
6843 if (i != 0) {
6844 ss << ", ";
6845 }
6846
6847 /* now get every prop of the collection */
6848 ss << RNA_pointer_as_string(C, ptr, prop, &itemptr).value_or("");
6849 }
6850
6851 RNA_property_collection_end(&collect_iter);
6852 ss << "]";
6853 break;
6854 }
6855 default:
6856 return "'<UNKNOWN TYPE>'"; /* TODO */
6857 }
6858
6859 return ss.str();
6860}
6861
6862/* Function */
6863
6865{
6866 return func->identifier;
6867}
6868
6870{
6871 return TIP_(func->description);
6872}
6873
6875{
6876 return func->description;
6877}
6878
6880{
6881 return func->flag;
6882}
6883
6885{
6886 return func->call != nullptr;
6887}
6888
6890{
6891 return static_cast<PropertyRNA *>(BLI_findlink(&func->cont.properties, index));
6892}
6893
6895 FunctionRNA *func,
6896 const char *identifier)
6897{
6898 PropertyRNA *parm;
6899
6900 parm = static_cast<PropertyRNA *>(func->cont.properties.first);
6901 for (; parm; parm = parm->next) {
6902 if (STREQ(RNA_property_identifier(parm), identifier)) {
6903 break;
6904 }
6905 }
6906
6907 return parm;
6908}
6909
6911{
6912 return &func->cont.properties;
6913}
6914
6915/* Utility */
6916
6918{
6919 return int(rna_ensure_property(prop)->flag_parameter);
6920}
6921
6923 PointerRNA * /*ptr*/,
6924 FunctionRNA *func)
6925{
6926 PointerRNA null_ptr = PointerRNA_NULL;
6927 void *data;
6928 int alloc_size = 0, size;
6929
6930 parms->arg_count = 0;
6931 parms->ret_count = 0;
6932
6933 /* allocate data */
6934 LISTBASE_FOREACH (PropertyRNA *, parm, &func->cont.properties) {
6935 alloc_size += rna_parameter_size_pad(rna_parameter_size(parm));
6936
6937 if (parm->flag_parameter & PARM_OUTPUT) {
6938 parms->ret_count++;
6939 }
6940 else {
6941 parms->arg_count++;
6942 }
6943 }
6944
6945 parms->data = MEM_callocN(alloc_size, "RNA_parameter_list_create");
6946 parms->func = func;
6947 parms->alloc_size = alloc_size;
6948
6949 /* set default values */
6950 data = parms->data;
6951
6952 LISTBASE_FOREACH (PropertyRNA *, parm, &func->cont.properties) {
6953 size = rna_parameter_size(parm);
6954
6955 /* set length to 0, these need to be set later, see bpy_array.c's py_to_array */
6956 if (parm->flag & PROP_DYNAMIC) {
6957 ParameterDynAlloc *data_alloc = static_cast<ParameterDynAlloc *>(data);
6958 data_alloc->array_tot = 0;
6959 data_alloc->array = nullptr;
6960 }
6961 else if ((parm->flag_parameter & PARM_RNAPTR) && (parm->flag & PROP_THICK_WRAP)) {
6962 BLI_assert(parm->type == PROP_POINTER);
6963 new (static_cast<PointerRNA *>(data)) PointerRNA();
6964 }
6965
6966 if (!(parm->flag_parameter & PARM_REQUIRED) && !(parm->flag & PROP_DYNAMIC)) {
6967 switch (parm->type) {
6968 case PROP_BOOLEAN:
6969 if (parm->arraydimension) {
6971 &null_ptr, (BoolPropertyRNA *)parm, static_cast<bool *>(data));
6972 }
6973 else {
6974 memcpy(data, &((BoolPropertyRNA *)parm)->defaultvalue, size);
6975 }
6976 break;
6977 case PROP_INT:
6978 if (parm->arraydimension) {
6980 &null_ptr, (IntPropertyRNA *)parm, static_cast<int *>(data));
6981 }
6982 else {
6983 memcpy(data, &((IntPropertyRNA *)parm)->defaultvalue, size);
6984 }
6985 break;
6986 case PROP_FLOAT:
6987 if (parm->arraydimension) {
6989 &null_ptr, (FloatPropertyRNA *)parm, static_cast<float *>(data));
6990 }
6991 else {
6992 memcpy(data, &((FloatPropertyRNA *)parm)->defaultvalue, size);
6993 }
6994 break;
6995 case PROP_ENUM:
6996 memcpy(data, &((EnumPropertyRNA *)parm)->defaultvalue, size);
6997 break;
6998 case PROP_STRING: {
6999 const char *defvalue = ((StringPropertyRNA *)parm)->defaultvalue;
7000 if (defvalue && defvalue[0]) {
7001 /* Causes bug #29988, possibly this is only correct for thick wrapped
7002 * need to look further into it - campbell */
7003#if 0
7004 BLI_strncpy(data, defvalue, size);
7005#else
7006 memcpy(data, &defvalue, size);
7007#endif
7008 }
7009 break;
7010 }
7011 case PROP_POINTER:
7012 case PROP_COLLECTION:
7013 break;
7014 }
7015 }
7016
7017 data = ((char *)data) + rna_parameter_size_pad(size);
7018 }
7019
7020 return parms;
7021}
7022
7024{
7025 PropertyRNA *parm;
7026
7027 parm = static_cast<PropertyRNA *>(parms->func->cont.properties.first);
7028 void *data = parms->data;
7029 for (; parm; parm = parm->next) {
7030 if (parm->type == PROP_COLLECTION) {
7031 CollectionVector *vector = static_cast<CollectionVector *>(data);
7032 vector->~CollectionVector();
7033 }
7034 else if ((parm->flag_parameter & PARM_RNAPTR) && (parm->flag & PROP_THICK_WRAP)) {
7035 BLI_assert(parm->type == PROP_POINTER);
7036 PointerRNA *ptr = static_cast<PointerRNA *>(data);
7037 /* #RNA_parameter_list_create ensures that 'thick wrap' PointerRNA parameters are
7038 * constructed. */
7039 ptr->~PointerRNA();
7040 }
7041 else if (parm->flag & PROP_DYNAMIC) {
7042 /* for dynamic arrays and strings, data is a pointer to an array */
7043 ParameterDynAlloc *data_alloc = static_cast<ParameterDynAlloc *>(data);
7044 if (data_alloc->array) {
7045 MEM_freeN(data_alloc->array);
7046 }
7047 }
7048 data = static_cast<char *>(data) + rna_parameter_size_pad(rna_parameter_size(parm));
7049 }
7050
7051 MEM_freeN(parms->data);
7052 parms->data = nullptr;
7053
7054 parms->func = nullptr;
7055}
7056
7058{
7059 return parms->alloc_size;
7060}
7061
7063{
7064 return parms->arg_count;
7065}
7066
7068{
7069 return parms->ret_count;
7070}
7071
7073{
7074 /* may be useful but unused now */
7075 // RNA_pointer_create_discrete(nullptr, &RNA_Function, parms->func, &iter->funcptr); /* UNUSED */
7076
7077 iter->parms = parms;
7078 iter->parm = static_cast<PropertyRNA *>(parms->func->cont.properties.first);
7079 iter->valid = iter->parm != nullptr;
7080 iter->offset = 0;
7081
7082 if (iter->valid) {
7083 iter->size = rna_parameter_size(iter->parm);
7084 iter->data = ((char *)iter->parms->data); /* +iter->offset, always 0 */
7085 }
7086}
7087
7089{
7090 iter->offset += rna_parameter_size_pad(iter->size);
7091 iter->parm = iter->parm->next;
7092 iter->valid = iter->parm != nullptr;
7093
7094 if (iter->valid) {
7095 iter->size = rna_parameter_size(iter->parm);
7096 iter->data = (((char *)iter->parms->data) + iter->offset);
7097 }
7098}
7099
7101{
7102 /* nothing to do */
7103}
7104
7105void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **r_value)
7106{
7107 ParameterIterator iter;
7108
7109 RNA_parameter_list_begin(parms, &iter);
7110
7111 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7112 if (iter.parm == parm) {
7113 break;
7114 }
7115 }
7116
7117 if (iter.valid) {
7118 if (parm->flag & PROP_DYNAMIC) {
7119 /* for dynamic arrays and strings, data is a pointer to an array */
7120 ParameterDynAlloc *data_alloc = static_cast<ParameterDynAlloc *>(iter.data);
7121 *r_value = data_alloc->array;
7122 }
7123 else {
7124 *r_value = iter.data;
7125 }
7126 }
7127 else {
7128 *r_value = nullptr;
7129 }
7130
7132}
7133
7134void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void **r_value)
7135{
7136 PropertyRNA *parm;
7137
7138 parm = static_cast<PropertyRNA *>(parms->func->cont.properties.first);
7139 for (; parm; parm = parm->next) {
7140 if (STREQ(RNA_property_identifier(parm), identifier)) {
7141 break;
7142 }
7143 }
7144
7145 if (parm) {
7146 RNA_parameter_get(parms, parm, r_value);
7147 }
7148}
7149
7150void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *value)
7151{
7152 ParameterIterator iter;
7153
7154 RNA_parameter_list_begin(parms, &iter);
7155
7156 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7157 if (iter.parm == parm) {
7158 break;
7159 }
7160 }
7161
7162 if (iter.valid) {
7163 if (parm->flag & PROP_DYNAMIC) {
7164 /* for dynamic arrays and strings, data is a pointer to an array */
7165 ParameterDynAlloc *data_alloc = static_cast<ParameterDynAlloc *>(iter.data);
7166 size_t size = 0;
7167 switch (parm->type) {
7168 case PROP_STRING:
7169 size = sizeof(char);
7170 break;
7171 case PROP_INT:
7172 case PROP_BOOLEAN:
7173 size = sizeof(int);
7174 break;
7175 case PROP_FLOAT:
7176 size = sizeof(float);
7177 break;
7178 default:
7179 break;
7180 }
7181 size *= data_alloc->array_tot;
7182 if (data_alloc->array) {
7183 MEM_freeN(data_alloc->array);
7184 }
7185 data_alloc->array = MEM_mallocN(size, __func__);
7186 memcpy(data_alloc->array, value, size);
7187 }
7188 else if ((parm->flag_parameter & PARM_RNAPTR) && (parm->flag & PROP_THICK_WRAP)) {
7189 BLI_assert(parm->type == PROP_POINTER);
7190 BLI_assert(iter.size == sizeof(PointerRNA));
7191 PointerRNA *ptr = static_cast<PointerRNA *>(iter.data);
7192 /* #RNA_parameter_list_create ensures that 'thick wrap' PointerRNA parameters are
7193 * constructed. */
7194 *ptr = PointerRNA(*static_cast<const PointerRNA *>(value));
7195 }
7196 else {
7197 memcpy(iter.data, value, iter.size);
7198 }
7199 }
7200
7202}
7203
7204void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, const void *value)
7205{
7206 PropertyRNA *parm;
7207
7208 parm = static_cast<PropertyRNA *>(parms->func->cont.properties.first);
7209 for (; parm; parm = parm->next) {
7210 if (STREQ(RNA_property_identifier(parm), identifier)) {
7211 break;
7212 }
7213 }
7214
7215 if (parm) {
7216 RNA_parameter_set(parms, parm, value);
7217 }
7218}
7219
7221{
7222 ParameterIterator iter;
7223 int len = 0;
7224
7225 RNA_parameter_list_begin(parms, &iter);
7226
7227 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7228 if (iter.parm == parm) {
7229 break;
7230 }
7231 }
7232
7233 if (iter.valid) {
7234 len = RNA_parameter_dynamic_length_get_data(parms, parm, iter.data);
7235 }
7236
7238
7239 return len;
7240}
7241
7243{
7244 ParameterIterator iter;
7245
7246 RNA_parameter_list_begin(parms, &iter);
7247
7248 for (; iter.valid; RNA_parameter_list_next(&iter)) {
7249 if (iter.parm == parm) {
7250 break;
7251 }
7252 }
7253
7254 if (iter.valid) {
7256 }
7257
7259}
7260
7262{
7263 if (parm->flag & PROP_DYNAMIC) {
7264 return int(((ParameterDynAlloc *)data)->array_tot);
7265 }
7266 return 0;
7267}
7268
7270 PropertyRNA *parm,
7271 void *data,
7272 int length)
7273{
7274 if (parm->flag & PROP_DYNAMIC) {
7275 ((ParameterDynAlloc *)data)->array_tot = intptr_t(length);
7276 }
7277}
7278
7280 bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
7281{
7282 if (func->call) {
7283 func->call(C, reports, ptr, parms);
7284
7285 return 0;
7286 }
7287
7288 return -1;
7289}
7290
7291std::optional<blender::StringRefNull> RNA_translate_ui_text(
7292 const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, int translate)
7293{
7294 return rna_translate_ui_text(text, text_ctxt, type, prop, translate);
7295}
7296
7298{
7299 int len;
7300
7301 /* get the length of the array to work with */
7303
7304 /* get and set the default values as appropriate for the various types */
7305 switch (RNA_property_type(prop)) {
7306 case PROP_BOOLEAN:
7307 if (len) {
7308 if (index == -1) {
7309 bool *tmparray = MEM_calloc_arrayN<bool>(len, __func__);
7310
7312 RNA_property_boolean_set_array(ptr, prop, tmparray);
7313
7314 MEM_freeN(tmparray);
7315 }
7316 else {
7317 int value = RNA_property_boolean_get_default_index(ptr, prop, index);
7318 RNA_property_boolean_set_index(ptr, prop, index, value);
7319 }
7320 }
7321 else {
7322 int value = RNA_property_boolean_get_default(ptr, prop);
7323 RNA_property_boolean_set(ptr, prop, value);
7324 }
7325 return true;
7326 case PROP_INT:
7327 if (len) {
7328 if (index == -1) {
7329 int *tmparray = MEM_calloc_arrayN<int>(len, __func__);
7330
7331 RNA_property_int_get_default_array(ptr, prop, tmparray);
7332 RNA_property_int_set_array(ptr, prop, tmparray);
7333
7334 MEM_freeN(tmparray);
7335 }
7336 else {
7337 int value = RNA_property_int_get_default_index(ptr, prop, index);
7338 RNA_property_int_set_index(ptr, prop, index, value);
7339 }
7340 }
7341 else {
7342 int value = RNA_property_int_get_default(ptr, prop);
7343 RNA_property_int_set(ptr, prop, value);
7344 }
7345 return true;
7346 case PROP_FLOAT:
7347 if (len) {
7348 if (index == -1) {
7349 float *tmparray = MEM_calloc_arrayN<float>(len, __func__);
7350
7352 RNA_property_float_set_array(ptr, prop, tmparray);
7353
7354 MEM_freeN(tmparray);
7355 }
7356 else {
7357 float value = RNA_property_float_get_default_index(ptr, prop, index);
7358 RNA_property_float_set_index(ptr, prop, index, value);
7359 }
7360 }
7361 else {
7362 float value = RNA_property_float_get_default(ptr, prop);
7363 RNA_property_float_set(ptr, prop, value);
7364 }
7365 return true;
7366 case PROP_ENUM: {
7367 int value = RNA_property_enum_get_default(ptr, prop);
7368 RNA_property_enum_set(ptr, prop, value);
7369 return true;
7370 }
7371
7372 case PROP_STRING: {
7373 char *value = RNA_property_string_get_default_alloc(ptr, prop, nullptr, 0, nullptr);
7374 RNA_property_string_set(ptr, prop, value);
7375 MEM_freeN(value);
7376 return true;
7377 }
7378
7379 case PROP_POINTER: {
7381 RNA_property_pointer_set(ptr, prop, value, nullptr);
7382 return true;
7383 }
7384
7385 default:
7386 /* FIXME: are there still any cases that haven't been handled?
7387 * comment out "default" block to check :) */
7388 return false;
7389 }
7390}
7391
7393{
7395 return false;
7396 }
7397
7398 /* get and set the default values as appropriate for the various types */
7399 switch (RNA_property_type(prop)) {
7400 case PROP_INT: {
7401 int value = RNA_property_int_get(ptr, prop);
7402 return RNA_property_int_set_default(prop, value);
7403 }
7404
7405 case PROP_FLOAT: {
7406 float value = RNA_property_float_get(ptr, prop);
7407 return RNA_property_float_set_default(prop, value);
7408 }
7409
7410 default:
7411 return false;
7412 }
7413}
7414
7415#ifdef WITH_PYTHON
7416extern void PyC_LineSpit();
7417#endif
7418
7419void _RNA_warning(const char *format, ...)
7420{
7421 va_list args;
7422
7423 va_start(args, format);
7424 vprintf(format, args);
7425 va_end(args);
7426
7427 /* gcc macro adds '\n', but can't use for other compilers */
7428#ifndef __GNUC__
7429 fputc('\n', stdout);
7430#endif
7431
7432#ifdef WITH_PYTHON
7433 {
7434 PyC_LineSpit();
7435 }
7436#endif
7437}
7438
7440 PropertyRNA *prop,
7441 const int prop_index,
7442 PathResolvedRNA *r_anim_rna)
7443{
7444 int array_len = RNA_property_array_length(ptr, prop);
7445
7446 if ((array_len == 0) || (prop_index < array_len)) {
7447 r_anim_rna->ptr = *ptr;
7448 r_anim_rna->prop = prop;
7449 r_anim_rna->prop_index = array_len ? prop_index : -1;
7450
7451 return true;
7452 }
7453 return false;
7454}
7455
7456static char rna_struct_state_owner[128];
7458{
7459 if (name) {
7461 }
7462 else {
7463 rna_struct_state_owner[0] = '\0';
7464 }
7465}
7466
7468{
7469 if (rna_struct_state_owner[0]) {
7471 }
7472 return nullptr;
7473}
bool id_can_have_animdata(const ID *id)
Definition anim_data.cc:73
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
wmMsgBus * CTX_wm_message_bus(const bContext *C)
FCurve * BKE_fcurve_find_by_rna(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **r_adt, bAction **r_action, bool *r_driven, bool *r_special)
#define G_MAIN
#define IDP_int_or_bool_set(prop, value)
#define IDP_ID_get(prop)
#define IDP_float_get(prop)
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:747
void IDP_FreeFromGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:741
eIDPropertyUIDataType IDP_ui_data_type(const IDProperty *prop)
Definition idprop.cc:1691
#define IDP_bool_set(prop, value)
void IDP_AssignStringMaxSize(IDProperty *prop, const char *st, size_t st_maxncpy) ATTR_NONNULL()
Definition idprop.cc:421
#define IDP_int_get(prop)
#define IDP_array_double_get(prop)
void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist, int flag)
Definition idprop.cc:645
@ IDP_UI_DATA_TYPE_BOOLEAN
@ IDP_UI_DATA_TYPE_INT
IDProperty * IDP_GetIndexArray(IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:130
#define IDP_int_set(prop, value)
#define IDP_string_get(prop)
#define IDP_double_get(prop)
IDProperty * IDP_New(char type, const IDPropertyTemplate *val, blender::StringRef name, eIDPropertyFlag flags={}) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:1009
#define IDP_array_bool_get(prop)
#define IDP_array_int_get(prop)
void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
Definition idprop.cc:153
#define IDP_property_array_get(prop)
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:717
void IDP_AppendArray(IDProperty *prop, IDProperty *item)
Definition idprop.cc:137
void IDP_AssignID(IDProperty *prop, ID *id, int flag)
Definition idprop.cc:546
void IDP_ResizeArray(IDProperty *prop, int newlen)
Definition idprop.cc:220
#define IDP_int_or_bool_get(prop)
IDProperty * IDP_NewStringMaxSize(const char *st, size_t st_maxncpy, blender::StringRef name, eIDPropertyFlag flags={}) ATTR_WARN_UNUSED_RESULT
Definition idprop.cc:363
#define IDP_float_set(prop, value)
IDPropertyUIData * IDP_ui_data_ensure(IDProperty *prop)
Definition idprop.cc:1761
void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:666
#define IDP_double_set(prop, value)
#define IDP_array_float_get(prop)
IDProperty * IDP_NewIDPArray(blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:67
#define IDP_bool_get(prop)
bool BKE_id_can_use_id(const ID &id_from, const ID &id_to)
Definition lib_id.cc:2528
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
IDOverrideLibrary * BKE_lib_override_library_get(Main *bmain, ID *id, ID *owner_id_hint, ID **r_owner_id)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
eReportType
Definition BKE_report.hh:33
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define BLI_INLINE
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.cc:37
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition BLI_dynstr.cc:56
GHash * BLI_ghash_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_kdtree_nd_ free(KDTree *tree)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring_ptr(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:651
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE int mod_i(int i, int n)
ATTR_WARN_UNUSED_RESULT const size_t num
#define BLI_string_debug_size(str, str_maxncpy)
Definition BLI_string.h:676
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define UNUSED_VARS(...)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
bool BLT_translate_iface()
#define TIP_(msgid)
const char * BLT_pgettext(const char *msgctxt, const char *msgid)
#define CTX_IFACE_(context, msgid)
const char * BLT_translate_do_tooltip(const char *msgctxt, const char *msgid)
bool BLT_translate_tooltips()
const char * BLT_translate_do_iface(const char *msgctxt, const char *msgid)
void BPY_free_srna_pytype(StructRNA *srna)
Definition bpy_rna.cc:10084
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
ID and Library types, which are fundamental for SDNA.
#define ID_REFCOUNTING_USERS(id)
Definition DNA_ID.h:681
#define ID_TYPE_USE_COPY_ON_EVAL(_id_type)
Definition DNA_ID.h:740
@ ID_RECALC_PARAMETERS
Definition DNA_ID.h:1138
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1054
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define ID_IS_EDITABLE(_id)
Definition DNA_ID.h:705
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition DNA_ID.h:730
@ ID_FLAG_EMBEDDED_DATA
Definition DNA_ID.h:774
@ ID_NT
@ IDP_STRING_SUB_BYTE
@ IDP_DOUBLE
@ IDP_FLOAT
@ IDP_STRING
@ IDP_BOOLEAN
@ IDP_IDPARRAY
@ IDP_INT
@ IDP_GROUP
@ IDP_ARRAY
@ IDP_ID
@ IDP_FLAG_GHOST
@ IDP_FLAG_STATIC_TYPE
@ IDP_FLAG_OVERRIDELIBRARY_LOCAL
#define IDP_NUMTYPES
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define RNA_PROP_END
#define RNA_STRUCT_BEGIN(sptr, prop)
#define RNA_STRUCT_END
#define RNA_PROP_BEGIN(sptr, itemptr, prop)
StructRNA * ID_code_to_RNA_type(short idcode)
#define RNA_MAX_ARRAY_LENGTH
Definition RNA_define.hh:24
#define RNA_MAX_ARRAY_DIMENSION
Definition RNA_define.hh:27
@ PARM_RNAPTR
Definition RNA_types.hh:547
@ PARM_REQUIRED
Definition RNA_types.hh:545
@ PARM_OUTPUT
Definition RNA_types.hh:546
bool(*)(CollectionPropertyIterator *iter, void *data) IteratorSkipFunc
Definition RNA_types.hh:563
PropertyScaleType
Definition RNA_types.hh:203
@ PROP_SCALE_LINEAR
Definition RNA_types.hh:205
@ STRUCT_NO_CONTEXT_WITHOUT_OWNER_ID
Definition RNA_types.hh:982
@ STRUCT_PUBLIC_NAMESPACE
Definition RNA_types.hh:974
@ STRUCT_ID
Definition RNA_types.hh:953
@ STRUCT_NO_DATABLOCK_IDPROPERTIES
Definition RNA_types.hh:970
@ STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES
Definition RNA_types.hh:972
@ STRUCT_NO_IDPROPERTIES
Definition RNA_types.hh:968
@ STRUCT_UNDO
Definition RNA_types.hh:961
eStringPropertySearchFlag
Definition RNA_types.hh:778
@ PROP_STRING_SEARCH_SUPPORTED
Definition RNA_types.hh:783
StructRNA *(*)(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) StructRegisterFunc
Definition RNA_types.hh:991
PropertyType
Definition RNA_types.hh:161
@ PROP_FLOAT
Definition RNA_types.hh:164
@ PROP_BOOLEAN
Definition RNA_types.hh:162
@ PROP_ENUM
Definition RNA_types.hh:166
@ PROP_INT
Definition RNA_types.hh:163
@ PROP_STRING
Definition RNA_types.hh:165
@ PROP_POINTER
Definition RNA_types.hh:167
@ PROP_COLLECTION
Definition RNA_types.hh:168
bool(*)(Main *bmain, StructRNA *type) StructUnregisterFunc
Definition RNA_types.hh:999
PropertyUnit
Definition RNA_types.hh:172
#define RNA_SUBTYPE_UNIT(subtype)
Definition RNA_types.hh:218
@ PROPOVERRIDE_LIBRARY_INSERTION
Definition RNA_types.hh:528
PropertyPathTemplateType
Definition RNA_types.hh:484
RawPropertyType
Definition RNA_types.hh:622
@ PROP_RAW_INT8
Definition RNA_types.hh:634
@ PROP_RAW_UINT64
Definition RNA_types.hh:633
@ PROP_RAW_INT
Definition RNA_types.hh:624
@ PROP_RAW_INT64
Definition RNA_types.hh:632
@ PROP_RAW_UNSET
Definition RNA_types.hh:623
@ PROP_RAW_BOOLEAN
Definition RNA_types.hh:627
@ PROP_RAW_CHAR
Definition RNA_types.hh:626
@ PROP_RAW_FLOAT
Definition RNA_types.hh:629
@ PROP_RAW_DOUBLE
Definition RNA_types.hh:628
@ PROP_RAW_UINT8
Definition RNA_types.hh:630
@ PROP_RAW_UINT16
Definition RNA_types.hh:631
@ PROP_RAW_SHORT
Definition RNA_types.hh:625
@ PROP_THICK_WRAP
Definition RNA_types.hh:423
@ PROP_DYNAMIC
Definition RNA_types.hh:428
@ PROP_CONTEXT_UPDATE
Definition RNA_types.hh:407
@ PROP_ANIMATABLE
Definition RNA_types.hh:319
@ PROP_NEVER_UNLINK
Definition RNA_types.hh:384
@ PROP_EDITABLE
Definition RNA_types.hh:306
@ PROP_ENUM_FLAG
Definition RNA_types.hh:404
@ PROP_LIB_EXCEPTION
Definition RNA_types.hh:312
@ PROP_CONTEXT_PROPERTY_UPDATE
Definition RNA_types.hh:408
@ PROP_ENUM_NO_CONTEXT
Definition RNA_types.hh:430
@ PROP_NEVER_NULL
Definition RNA_types.hh:377
@ PROP_NO_DEG_UPDATE
Definition RNA_types.hh:439
@ PROP_ENUM_NO_TRANSLATE
Definition RNA_types.hh:432
@ PROP_REGISTER
Definition RNA_types.hh:411
@ PROP_DEG_SYNC_ONLY
Definition RNA_types.hh:445
@ PROP_ID_SELF_CHECK
Definition RNA_types.hh:370
@ PROP_ID_REFCOUNT
Definition RNA_types.hh:364
@ PROP_IDPROPERTY
Definition RNA_types.hh:426
PropertySubType
Definition RNA_types.hh:232
@ PROP_DIRECTION
Definition RNA_types.hh:262
@ PROP_XYZ
Definition RNA_types.hh:269
@ PROP_ACCELERATION
Definition RNA_types.hh:264
@ PROP_BYTESTRING
Definition RNA_types.hh:240
@ PROP_COLOR
Definition RNA_types.hh:260
@ PROP_AXISANGLE
Definition RNA_types.hh:268
@ PROP_EULER
Definition RNA_types.hh:266
@ PROP_COORDS
Definition RNA_types.hh:274
@ PROP_COLOR_GAMMA
Definition RNA_types.hh:272
@ PROP_TRANSLATION
Definition RNA_types.hh:261
@ PROP_XYZ_LENGTH
Definition RNA_types.hh:270
@ PROP_QUATERNION
Definition RNA_types.hh:267
@ PROP_VELOCITY
Definition RNA_types.hh:263
#define C
Definition RandGen.cpp:29
#define ND_SHADING
Definition WM_types.hh:477
#define NC_WINDOW
Definition WM_types.hh:375
#define NC_ID
Definition WM_types.hh:395
#define NA_EDITED
Definition WM_types.hh:584
#define NC_MATERIAL
Definition WM_types.hh:380
volatile int lock
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
Span< T > as_span() const
Definition BLI_array.hh:243
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:248
const T * data() const
Definition BLI_array.hh:312
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:419
constexpr T * data() const
Definition BLI_span.hh:539
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
constexpr const T * data() const
Definition BLI_span.hh:215
nullptr float
#define offsetof(t, d)
#define str(s)
#define GS(x)
uint pos
ThreadMutex mutex
#define in
#define out
#define main()
#define printf(...)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
float length(VecOp< float, D >) RET
format
#define LOG(level)
Definition log.h:97
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
std::unique_ptr< IDProperty, IDPropertyDeleter > create_bool(StringRef prop_name, bool value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_BOOLEAN, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRef prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRef prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
std::mutex Mutex
Definition BLI_mutex.hh:47
void PyC_LineSpit()
const char * name
return ret
PointerRNA rna_listbase_lookup_int(PointerRNA *ptr, StructRNA *type, ListBase *lb, int index)
StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_is_runtime(const PropertyRNA *prop)
bool RNA_property_collection_lookup_int_has_fn(PropertyRNA *prop)
void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const bool *values)
bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
StructRegisterFunc RNA_struct_register(StructRNA *type)
bool RNA_property_enum_item_from_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
IDProperty * rna_idproperty_find(PointerRNA *ptr, const char *name)
PointerRNA RNA_pointer_create_id_subdata(ID &id, StructRNA *type, void *data)
void RNA_property_float_get_default_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
static void property_float_get_array(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id, blender::MutableSpan< float > r_values)
bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
int RNA_enum_bitflag_identifiers(const EnumPropertyItem *item, const int value, const char **r_identifier)
static void rna_property_float_fill_default_array_values_double(const double *default_array, const int default_array_len, const double default_value, const int out_length, float *r_values)
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, bool value)
void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
const StructRNA * RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
std::optional< AncestorPointerRNA > RNA_struct_search_closest_ancestor_by_type(PointerRNA *ptr, const StructRNA *srna)
PropertyRNA * RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
const char * RNA_property_ui_description(const PropertyRNA *prop)
bool RNA_property_update_check(PropertyRNA *prop)
bool RNA_property_array_check(PropertyRNA *prop)
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
PropertyRNA * RNA_struct_find_collection_property_check(PointerRNA &props, const char *name, const StructRNA *struct_type_check)
bool RNA_property_is_unlink(PropertyRNA *prop)
std::string RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **r_value)
void rna_property_rna_or_id_get(PropertyRNA *prop, PointerRNA *ptr, PropertyRNAOrID *r_prop_rna_or_id)
StructRNA * RNA_struct_find(const char *identifier)
static void rna_property_int_fill_default_array_values(const int *defarr, int defarr_length, int defvalue, int out_length, int *r_values)
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
bool RNA_property_assign_default(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_function_identifier(FunctionRNA *func)
void RNA_parameter_list_end(ParameterIterator *)
PropertyScaleType RNA_property_ui_scale(PropertyRNA *prop)
void RNA_struct_state_owner_set(const char *name)
bool RNA_property_int_set_default(PropertyRNA *prop, int value)
void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
void rna_iterator_array_end(CollectionPropertyIterator *iter)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
static void rna_property_int_get_default_array_values(PointerRNA *ptr, IntPropertyRNA *iprop, int *r_values)
IDProperty ** RNA_struct_idprops_p(PointerRNA *ptr)
bool RNA_property_float_set_default(PropertyRNA *prop, float value)
void RNA_property_int_get_array_at_most(PointerRNA *ptr, PropertyRNA *prop, int *values, int values_num)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
static void rna_property_float_get_default_array_values(PointerRNA *ptr, FloatPropertyRNA *fprop, float *r_values)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
int RNA_collection_length(PointerRNA *ptr, const char *name)
int RNA_enum_from_name(const EnumPropertyItem *item, const char *name)
bool RNA_struct_system_idprops_unset(PointerRNA *ptr, const char *identifier)
IDProperty ** RNA_struct_system_idprops_p(PointerRNA *ptr)
int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
int RNA_parameter_dynamic_length_get_data(ParameterList *, PropertyRNA *parm, void *data)
int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
static size_t property_string_length_storage(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
int RNA_property_int_get_default(PointerRNA *ptr, PropertyRNA *prop)
void RNA_exit()
void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
void RNA_boolean_get_array(PointerRNA *ptr, const char *name, bool *values)
int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_identifier)
bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
bool RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname)
PropertyRNA * RNA_struct_find_property_check(PointerRNA &props, const char *name, const PropertyType property_type_check)
bool RNA_struct_is_ID(const StructRNA *type)
int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
char * RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
const ListBase * RNA_struct_type_properties(StructRNA *srna)
void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
bool RNA_enum_value_from_id(const EnumPropertyItem *item, const char *identifier, int *r_value)
const ListBase * RNA_struct_type_functions(StructRNA *srna)
PropertyRNA * rna_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
bool RNA_struct_idprops_check(const StructRNA *srna)
void rna_iterator_listbase_end(CollectionPropertyIterator *)
bool RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
static void rna_property_boolean_get_default_array_values(PointerRNA *ptr, BoolPropertyRNA *bprop, bool *r_values)
eStringPropertySearchFlag RNA_property_string_search_flag(PropertyRNA *prop)
bool RNA_property_collection_is_empty(PointerRNA *ptr, PropertyRNA *prop)
PropertyUnit RNA_property_unit(PropertyRNA *prop)
void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
int RNA_function_defined(FunctionRNA *func)
int RNA_property_ui_icon(const PropertyRNA *prop)
static const char * rna_ensure_property_identifier(const PropertyRNA *prop)
int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, const PointerRNA *t_ptr)
void RNA_collection_clear(PointerRNA *ptr, const char *name)
bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index)
void RNA_parameter_dynamic_length_set(ParameterList *parms, PropertyRNA *parm, int length)
static void rna_array_as_string_elem(int type, void **buf_p, int len, std::stringstream &ss)
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
void RNA_parameter_dynamic_length_set_data(ParameterList *, PropertyRNA *parm, void *data, int length)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
bool RNA_path_resolved_create(PointerRNA *ptr, PropertyRNA *prop, const int prop_index, PathResolvedRNA *r_anim_rna)
bool RNA_collection_is_empty(PointerRNA *ptr, const char *name)
static const char * bool_as_py_string(const int var)
float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value, ReportList *reports)
void RNA_property_string_search(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *edit_text, blender::FunctionRef< void(StringPropertySearchVisitParams)> visit_fn)
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
void _RNA_warning(const char *format,...)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
const EnumPropertyItem * RNA_struct_property_tag_defines(const StructRNA *type)
void RNA_property_collection_skip(CollectionPropertyIterator *iter, int num)
#define RAW_GET(dtype, var, raw, a)
float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
void RNA_pointer_add(PointerRNA *ptr, const char *name)
bool RNA_property_collection_lookup_string_has_nameprop(PropertyRNA *prop)
int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
IDProperty * rna_system_idproperty_find(PointerRNA *ptr, const char *name)
int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *array, RawPropertyType type, int len)
BLI_INLINE void rna_pointer_refine(PointerRNA &r_ptr)
std::string RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, const bool as_function, const bool all_args, const bool nested_args, const int max_prop_length, PropertyRNA *iterprop)
uint RNA_enum_items_count(const EnumPropertyItem *item)
int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension)
bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost)
bool RNA_property_editable_index(const PointerRNA *ptr, PropertyRNA *prop, const int index)
int RNA_property_enum_get_default(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_ui_description_raw(const PropertyRNA *prop)
bool RNA_property_collection_lookup_string_supported(PropertyRNA *prop)
void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *value)
static void rna_system_idproperty_free(PointerRNA *ptr, const char *name)
bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost)
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_description(PropertyRNA *prop)
void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
bool RNA_enum_icon_from_value(const EnumPropertyItem *item, int value, int *r_icon)
void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop_orig)
void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
PropertyType RNA_property_type(PropertyRNA *prop)
const char * RNA_function_ui_description_raw(FunctionRNA *func)
const PointerRNA PointerRNA_NULL
char * RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen, int *r_len)
void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_int_set_array_at_most(PointerRNA *ptr, PropertyRNA *prop, const int *values, int values_num)
static PropertyRNA * arraytypemap[IDP_NUMTYPES]
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
PointerRNA RNA_property_pointer_get_default(PointerRNA *, PropertyRNA *)
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
void * RNA_struct_blender_type_get(StructRNA *srna)
void RNA_property_float_get_array_at_most(PointerRNA *ptr, PropertyRNA *prop, float *values, int values_num)
void ** RNA_struct_instance(PointerRNA *ptr)
char RNA_property_array_item_char(PropertyRNA *prop, int index)
int RNA_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
void RNA_parameter_list_free(ParameterList *parms)
static const char * rna_ensure_property_name(const PropertyRNA *prop)
bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
std::string RNA_pointer_as_string_keywords(bContext *C, PointerRNA *ptr, const bool as_function, const bool all_args, const bool nested_args, const int max_prop_length)
IDProperty * RNA_struct_idprops(PointerRNA *ptr, bool create)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
void rna_idproperty_touch(IDProperty *idprop)
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
size_t RNA_raw_type_sizeof(RawPropertyType type)
bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
void RNA_property_boolean_get_default_array(PointerRNA *ptr, PropertyRNA *prop, bool *values)
const char * RNA_struct_identifier(const StructRNA *type)
bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
void RNA_property_boolean_get_array_at_most(PointerRNA *ptr, PropertyRNA *prop, bool *values, int values_num)
void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
static int rna_property_array_length_all_dimensions(PointerRNA *ptr, PropertyRNA *prop)
static float property_float_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
bool RNA_enum_id_from_value(const EnumPropertyItem *item, int value, const char **r_identifier)
IDProperty * RNA_struct_system_idprops(PointerRNA *ptr, bool create)
PointerRNA rna_array_lookup_int(PointerRNA *ptr, StructRNA *type, void *data, size_t itemsize, int64_t length, int64_t index)
int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_translation_context(const PropertyRNA *prop)
void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, PointerRNA *ptr, ListBase *lb, IteratorSkipFunc skip)
void RNA_property_collection_next(CollectionPropertyIterator *iter)
char * RNA_struct_name_get_alloc_ex(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len, PropertyRNA **r_nameprop)
void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
void RNA_parameter_list_next(ParameterIterator *iter)
void * rna_iterator_array_get(CollectionPropertyIterator *iter)
void RNA_enum_set_identifier(bContext *C, PointerRNA *ptr, const char *name, const char *id)
const char * RNA_property_ui_name(const PropertyRNA *prop, const PointerRNA *ptr)
PropertyPathTemplateType RNA_property_path_template_type(PropertyRNA *prop)
static void * rna_array_as_string_alloc(int type, int len, PointerRNA *ptr, PropertyRNA *prop, void **r_buf_end)
void RNA_property_float_set_array_at_most(PointerRNA *ptr, PropertyRNA *prop, const float *values, int values_num)
static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
static int property_int_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
static void rna_property_float_fill_default_array_values(const float *defarr, int defarr_length, float defvalue, int out_length, float *r_values)
const char * RNA_function_ui_description(FunctionRNA *func)
int RNA_int_get(PointerRNA *ptr, const char *name)
static void rna_ensure_property_multi_array_length(const PointerRNA *ptr, PropertyRNA *prop, int length[])
int RNA_property_array_dimension(const PointerRNA *ptr, PropertyRNA *prop, int length[])
bool RNA_enum_value_from_identifier(const EnumPropertyItem *item, const char *identifier, int *r_value)
bool RNA_enum_name_from_value(const EnumPropertyItem *item, int value, const char **r_name)
PropertyRNA * RNA_struct_type_find_property_no_base(StructRNA *srna, const char *identifier)
int RNA_function_flag(FunctionRNA *func)
void * RNA_property_py_data_get(PropertyRNA *prop)
std::string RNA_function_as_string_keywords(bContext *C, FunctionRNA *func, const bool as_function, const bool all_args, const int max_prop_length)
void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
float RNA_property_float_get_default(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create_from_ancestor(const PointerRNA &ptr, const int ancestor_idx)
const DeprecatedRNA * RNA_property_deprecated(const PropertyRNA *prop)
std::optional< std::string > RNA_property_string_path_filter(const bContext *C, PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_anim_editable(const PointerRNA *ptr, PropertyRNA *prop_orig)
static bool rna_property_editable_do(const PointerRNA *ptr, PropertyRNA *prop_orig, const int index, const char **r_info)
bool RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
int RNA_property_flag(PropertyRNA *prop)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
RawPropertyType RNA_property_raw_type(PropertyRNA *prop)
static void rna_property_boolean_fill_default_array_values_from_ints(const int *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values)
const char * RNA_struct_ui_description_raw(const StructRNA *type)
int RNA_struct_ui_icon(const StructRNA *type)
void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_property_builtin(PropertyRNA *prop)
void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_struct_system_idprops_register_check(const StructRNA *type)
const char * RNA_struct_ui_description(const StructRNA *type)
int RNA_parameter_list_arg_count(const ParameterList *parms)
bool RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, const void *value)
static char rna_struct_state_owner[128]
void RNA_property_string_get_default(PropertyRNA *prop, char *value, const int value_maxncpy)
void RNA_property_string_set_bytes(PointerRNA *ptr, PropertyRNA *prop, const char *value, int len)
bool RNA_struct_system_idprops_check(StructRNA *srna)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
int RNA_string_length(PointerRNA *ptr, const char *name)
static PropertyRNA * typemap[IDP_NUMTYPES]
bool RNA_property_enum_item_from_value_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, EnumPropertyItem *r_item)
const char * RNA_struct_ui_name(const StructRNA *type)
bool RNA_struct_undo_check(const StructRNA *type)
void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter)
void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier)
void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
bool RNA_pointer_is_null(const PointerRNA *ptr)
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_enum_description(const EnumPropertyItem *item, const int value, const char **r_description)
StructRNA * RNA_struct_base(StructRNA *type)
static std::optional< std::string > rna_pointer_as_string__bldata(PointerRNA *ptr)
FunctionRNA * RNA_struct_find_function(StructRNA *srna, const char *identifier)
static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
bool RNA_property_is_idprop(const PropertyRNA *prop)
static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_string_maxlength(PropertyRNA *prop)
void RNA_property_enum_items_gettexted_all(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
const char * RNA_struct_state_owner_get()
std::optional< std::string > RNA_pointer_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop)
bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
static void rna_array_as_string(int type, int len, PointerRNA *ptr, PropertyRNA *prop, std::stringstream &ss)
int RNA_property_string_default_length(PointerRNA *, PropertyRNA *prop)
static bool property_boolean_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
bool RNA_property_editable(const PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_collection_lookup_string_index(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr, int *r_index)
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
void RNA_property_int_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
static bool property_collection_liboverride_editable(PointerRNA *ptr, PropertyRNA *prop, bool *r_is_liboverride)
bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
bool RNA_property_editable_info(const PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
void rna_iterator_array_begin(CollectionPropertyIterator *iter, PointerRNA *ptr, void *data, size_t itemsize, int64_t length, bool free_ptr, IteratorSkipFunc skip)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
void rna_iterator_array_next(CollectionPropertyIterator *iter)
PointerRNA RNA_pointer_recast(PointerRNA *ptr)
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
PropertyRNA * RNA_struct_name_property(const StructRNA *type)
static const char * rna_ensure_property_description(const PropertyRNA *prop)
std::string RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
PropertySubType RNA_property_subtype(PropertyRNA *prop)
static void property_int_get_array(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id, blender::MutableSpan< int > r_values)
static PointerRNA property_pointer_get(PointerRNA *ptr, PropertyRNA *prop, const bool do_create)
static std::string property_string_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
int RNA_parameter_list_ret_count(const ParameterList *parms)
PointerRNA RNA_main_pointer_create(Main *main)
void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void rna_pointer_create_with_ancestors(const PointerRNA &parent, StructRNA *type, void *data, PointerRNA &r_ptr)
int RNA_function_call(bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms)
int RNA_parameter_dynamic_length_get(ParameterList *parms, PropertyRNA *parm)
static void rna_array_as_string_recursive(int type, void **buf_p, int totdim, const int *dim_size, std::stringstream &ss)
const char * RNA_struct_ui_name_raw(const StructRNA *type)
bool RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
ParameterList * RNA_parameter_list_create(ParameterList *parms, PointerRNA *, FunctionRNA *func)
void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
std::optional< blender::StringRefNull > RNA_translate_ui_text(const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, int translate)
PropertyRNA * RNA_function_get_parameter(PointerRNA *, FunctionRNA *func, int index)
bool RNA_property_driver_editable(const PointerRNA *ptr, PropertyRNA *prop)
static int property_enum_get(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id)
void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
int RNA_property_tags(PropertyRNA *prop)
bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
void * rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
static bool rna_ensure_property_array_check(PropertyRNA *prop)
bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
void RNA_property_collection_end(CollectionPropertyIterator *iter)
bool RNA_property_collection_lookup_string_has_fn(PropertyRNA *prop)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
int RNA_property_array_item_index(PropertyRNA *prop, char name)
static void rna_property_boolean_fill_default_array_values(const bool *defarr, int defarr_length, bool defvalue, int out_length, bool *r_values)
PointerRNA RNA_blender_rna_pointer_create()
bool RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
bool RNA_property_boolean_get_default(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const char *identifier, const char *sep)
const char * RNA_property_ui_name_raw(const PropertyRNA *prop, const PointerRNA *ptr)
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
int RNA_enum_get(PointerRNA *ptr, const char *name)
void * rna_iterator_listbase_get(CollectionPropertyIterator *iter)
void RNA_bpy_exit()
#define RAW_SET(dtype, raw, a, var)
static void property_boolean_get_array(PointerRNA *ptr, PropertyRNAOrID &prop_rna_or_id, blender::MutableSpan< bool > r_values)
void RNA_property_unset(PointerRNA *ptr, PropertyRNA *prop)
uint RNA_struct_count_properties(StructRNA *srna)
void RNA_parameter_list_begin(ParameterList *parms, ParameterIterator *iter)
IDProperty * rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
void RNA_property_boolean_set_array_at_most(PointerRNA *ptr, PropertyRNA *prop, const bool *values, int values_num)
void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
std::string RNA_property_as_string(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length)
int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
PropertyRNA * RNA_struct_iterator_property(StructRNA *type)
void RNA_property_enum_items_ex(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const bool use_static, const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
void RNA_init()
Definition rna_access.cc:88
int RNA_parameter_list_size(const ParameterList *parms)
int RNA_parameter_flag(PropertyRNA *prop)
void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void **r_value)
void * RNA_struct_py_type_get(StructRNA *srna)
bool RNA_property_editable_flag(const PointerRNA *ptr, PropertyRNA *prop)
PointerRNA RNA_pointer_create_with_parent(const PointerRNA &parent, StructRNA *type, void *data)
PropertyRNA * RNA_function_find_parameter(PointerRNA *, FunctionRNA *func, const char *identifier)
const char * RNA_struct_translation_context(const StructRNA *type)
int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *array, RawPropertyType type, int len)
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
const char * RNA_property_identifier(const PropertyRNA *prop)
int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, bool set, RawArray *array)
const ListBase * RNA_function_defined_parameters(FunctionRNA *func)
static const char * rna_property_type_identifier(PropertyType prop_type)
PropertyRNA * rna_ensure_property(PropertyRNA *prop)
static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
bool RNA_enum_name_gettexted(const EnumPropertyItem *item, int value, const char *translation_context, const char **r_name)
int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const bool *values)
PointerRNA RNA_id_pointer_create(ID *id)
void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
PointerRNA RNA_property_pointer_get_never_create(PointerRNA *ptr, PropertyRNA *prop)
static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
bool RNA_property_overridable_get(const PointerRNA *ptr, PropertyRNA *prop)
void RNA_free(BlenderRNA *brna)
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
int rna_parameter_size(PropertyRNA *parm)
int rna_parameter_size_pad(const int size)
BlenderRNA BLENDER_RNA
std::optional< blender::StringRefNull > rna_translate_ui_text(const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, bool translate)
#define RNA_MAGIC
bool(*)(PointerRNA *ptr, const PointerRNA value, const PropertyRNA *prop) PropPointerPollFuncPy
void(*)(bContext *C, PointerRNA *ptr, PropertyRNA *prop) ContextPropUpdateFunc
void(*)(bContext *C, PointerRNA *ptr) ContextUpdateFunc
@ PROP_INTERN_BUILTIN
@ PROP_INTERN_RAW_ACCESS
@ PROP_INTERN_RAW_ARRAY
@ PROP_INTERN_RUNTIME
std::optional< std::string > RNA_path_full_struct_py(const PointerRNA *ptr)
Definition rna_path.cc:1267
std::string RNA_path_full_ID_py(ID *id)
Definition rna_path.cc:1232
std::optional< std::string > RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition rna_path.cc:1173
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:560
bool RNA_path_resolve(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition rna_path.cc:532
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
StructRNA * type
Definition RNA_types.hh:36
bAction * action
void * free_ptr
Definition RNA_types.hh:576
IteratorSkipFunc skip
Definition RNA_types.hh:590
PropBooleanArrayGetTransformFunc getarray_transform
PropBooleanGetFuncEx get_default
PropBooleanSetTransformFunc set_transform
PropBooleanArraySetFuncEx setarray_ex
PropBooleanArrayGetFuncEx getarray_ex
PropBooleanGetTransformFunc get_transform
PropBooleanArraySetFunc setarray
const bool * defaultarray
PropBooleanArrayGetFuncEx get_default_array
PropBooleanSetFunc set
PropBooleanGetFunc get
PropBooleanSetFuncEx set_ex
PropBooleanGetFuncEx get_ex
PropBooleanArraySetTransformFunc setarray_transform
PropBooleanArrayGetFunc getarray
union CollectionPropertyIterator::@220100362304005352221007113371015217044252346141 internal
ListBaseIterator listbase
Definition RNA_types.hh:606
PropCollectionNextFunc next
PropCollectionLookupStringFunc lookupstring
PropCollectionLengthFunc length
PropCollectionLookupIntFunc lookupint
PropCollectionBeginFunc begin
PropCollectionAssignIntFunc assignint
PropCollectionEndFunc end
blender::CustomIDVectorSet< PropertyRNA *, PropertyRNAIdentifierGetter > * prop_lookup_set
const char * identifier
Definition RNA_types.hh:657
const char * name
Definition RNA_types.hh:661
const char * description
Definition RNA_types.hh:663
const EnumPropertyItem * item
PropEnumSetFuncEx set_ex
PropEnumGetTransformFunc get_transform
PropEnumGetFuncEx get_default
PropEnumGetFunc get
PropEnumItemFunc item_fn
PropEnumSetTransformFunc set_transform
PropEnumGetFuncEx get_ex
PropEnumSetFunc set
PropFloatSetTransformFunc set_transform
PropFloatSetFuncEx set_ex
PropertyScaleType ui_scale_type
PropFloatGetFunc get
PropFloatRangeFuncEx range_ex
PropFloatArrayGetTransformFunc getarray_transform
PropFloatArrayGetFuncEx getarray_ex
PropFloatArraySetFuncEx setarray_ex
PropFloatArrayGetFunc getarray
PropFloatGetFuncEx get_default
PropFloatArraySetTransformFunc setarray_transform
PropFloatGetTransformFunc get_transform
PropFloatSetFunc set
const float * defaultarray
PropFloatRangeFunc range
PropFloatArraySetFunc setarray
PropFloatGetFuncEx get_ex
PropFloatArrayGetFuncEx get_default_array
const char * identifier
ContainerRNA cont
const char * description
struct ID * reference
Definition DNA_ID.h:334
void * pointer
Definition DNA_ID.h:142
int8_t * default_array
Definition DNA_ID.h:97
double * default_array
Definition DNA_ID.h:107
IDPropertyUIDataEnumItem * enum_items
Definition DNA_ID.h:91
int * default_array
Definition DNA_ID.h:80
char * description
Definition DNA_ID.h:56
short flag
Definition DNA_ID.h:163
int len
Definition DNA_ID.h:175
IDPropertyUIData * ui_data
Definition DNA_ID.h:183
char name[64]
Definition DNA_ID.h:164
IDPropertyData data
Definition DNA_ID.h:169
char subtype
Definition DNA_ID.h:161
char type
Definition DNA_ID.h:156
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
short flag
Definition DNA_ID.h:438
PropIntRangeFuncEx range_ex
PropIntArrayGetFunc getarray
PropIntArrayGetFuncEx getarray_ex
PropIntArraySetTransformFunc setarray_transform
PropIntRangeFunc range
PropIntArraySetFunc setarray
PropIntGetFuncEx get_ex
PropIntArrayGetFuncEx get_default_array
PropIntSetTransformFunc set_transform
PropIntArraySetFuncEx setarray_ex
PropIntGetTransformFunc get_transform
PropertyScaleType ui_scale_type
PropIntArrayGetTransformFunc getarray_transform
PropIntGetFuncEx get_default
PropIntSetFuncEx set_ex
IteratorSkipFunc skip
Definition RNA_types.hh:568
void * first
ParameterList * parms
Definition RNA_types.hh:853
PropertyRNA * parm
Definition RNA_types.hh:858
FunctionRNA * func
Definition RNA_types.hh:844
PointerRNA ptr
Definition RNA_types.hh:153
PropertyRNA * prop
Definition RNA_types.hh:154
PropPointerTypeFunc type_fn
PropPointerGetFunc get
PropPointerPollFunc poll
PropPointerSetFunc set
T * data_as() const
Definition RNA_types.hh:124
ID * owner_id
Definition RNA_types.hh:51
StructRNA * type
Definition RNA_types.hh:52
void * data
Definition RNA_types.hh:53
ItemEditableFunc itemeditable
PropArrayLengthGetFunc getlength
const char * translation_context
unsigned int arraydimension
const DeprecatedRNA * deprecated
EditableFunc editable
PropertyPathTemplateType path_template_type
PropUINameFunc ui_name_func
PropertyRNA * next
PropertySubType subtype
unsigned int arraylength[RNA_MAX_ARRAY_DIMENSION]
const char * description
const char * name
unsigned int totarraylength
const char * identifier
RawPropertyType rawtype
PropertyType type
StringPropertyPathFilterFunc path_filter
PropStringSetFunc set
PropStringLengthFuncEx length_ex
PropStringLengthFunc length
PropStringGetFuncEx get_ex
PropStringSetFuncEx set_ex
PropStringGetTransformFunc get_transform
PropStringSetTransformFunc set_transform
PropStringGetFunc get
StringPropertySearchFunc search
eStringPropertySearchFlag search_flag
StructRegisterFunc reg
StructUnregisterFunc unreg
const char * name
const char * identifier
StructInstanceFunc instance
ContainerRNA cont
const char * translation_context
const EnumPropertyItem * prop_tag_defines
PropertyRNA * nameproperty
const char * description
IDPropertiesFunc idproperties
PropertyRNA * iteratorproperty
StructRNA * base
StructRefineFunc refine
IDPropertiesFunc system_idproperties
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
struct IDPropertyTemplate::@032057005265002020267344110225167212360002125060 array
const char * str
Definition BKE_idprop.hh:39
struct IDPropertyTemplate::@306303166102371126056157213146124155011254157272 string
uint len
#define N_(msgid)
void WM_main_add_notifier(uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4238
void WM_msg_publish_rna(wmMsgBus *mbus, PointerRNA *ptr, PropertyRNA *prop)
uint8_t flag
Definition wm_window.cc:145