2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Blender Foundation (2008).
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/makesrna/intern/rna_access.c
33 #include "MEM_guardedalloc.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_windowmanager_types.h"
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_dynstr.h"
42 #include "BLI_ghash.h"
46 #include "BLT_translation.h"
48 #include "BKE_animsys.h"
49 #include "BKE_context.h"
50 #include "BKE_idcode.h"
51 #include "BKE_idprop.h"
52 #include "BKE_fcurve.h"
53 #include "BKE_library.h"
54 #include "BKE_library_override.h"
56 #include "BKE_report.h"
58 #include "DEG_depsgraph.h"
60 #include "RNA_access.h"
61 #include "RNA_define.h"
62 #include "RNA_enum_types.h"
65 #include "WM_message.h"
68 #include "DNA_object_types.h"
71 #include "rna_internal.h"
73 const PointerRNA PointerRNA_NULL = {{NULL}};
82 BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
83 BLENDER_RNA.structs_len = 0;
85 for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
86 if (!srna->cont.prophash) {
87 srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
89 for (prop = srna->cont.properties.first; prop; prop = prop->next) {
90 if (!(prop->flag_internal & PROP_INTERN_BUILTIN)) {
91 BLI_ghash_insert(srna->cont.prophash, (void *)prop->identifier, prop);
95 BLI_assert(srna->flag & STRUCT_PUBLIC_NAMESPACE);
96 BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
97 BLENDER_RNA.structs_len += 1;
105 RNA_property_update_cache_free();
107 for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
108 if (srna->cont.prophash) {
109 BLI_ghash_free(srna->cont.prophash, NULL, NULL);
110 srna->cont.prophash = NULL;
114 RNA_free(&BLENDER_RNA);
119 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
121 r_ptr->id.data = NULL;
122 r_ptr->type = &RNA_BlendData;
126 void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
128 StructRNA *type, *idtype = NULL;
131 PointerRNA tmp = {{NULL}};
133 idtype = rna_ID_refine(&tmp);
135 while (idtype->refine) {
136 type = idtype->refine(&tmp);
146 r_ptr->type = idtype;
150 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
153 StructRNA *idtype = NULL;
156 PointerRNA tmp = {{0}};
158 idtype = rna_ID_refine(&tmp);
167 while (r_ptr->type && r_ptr->type->refine) {
168 StructRNA *rtype = r_ptr->type->refine(r_ptr);
170 if (rtype == r_ptr->type)
178 bool RNA_pointer_is_null(const PointerRNA *ptr)
180 return !((ptr->data != NULL) && (ptr->id.data != NULL) && (ptr->type != NULL));
183 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
185 if (type && type->flag & STRUCT_ID) {
186 ptr->id.data = ptr->data;
189 ptr->id.data = parent->id.data;
193 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
195 r_ptr->id.data = NULL;
196 r_ptr->type = &RNA_BlenderRNA;
197 r_ptr->data = &BLENDER_RNA;
200 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
206 rna_pointer_inherit_id(type, ptr, &result);
208 while (result.type->refine) {
209 type = result.type->refine(&result);
211 if (type == result.type)
219 return PointerRNA_NULL;
224 void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
226 #if 0 /* works but this case if covered by more general code below. */
227 if (RNA_struct_is_ID(ptr->type)) {
229 RNA_id_pointer_create(ptr->id.data, r_ptr);
236 *r_ptr = *ptr; /* initialize as the same in case cant recast */
238 for (base = ptr->type->base; base; base = base->base) {
239 t_ptr = rna_pointer_inherit_refine(ptr, base, ptr->data);
240 if (t_ptr.type && t_ptr.type != ptr->type) {
249 static void rna_idproperty_touch(IDProperty *idprop)
251 /* so the property is seen as 'set' by rna */
252 idprop->flag &= ~IDP_FLAG_GHOST;
255 /* return a UI local ID prop definition for this prop */
256 static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
260 for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
261 if (STREQ(RNA_IDP_UI, idprop->name))
265 if (idprop == NULL) {
266 for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
267 if (STREQ(RNA_IDP_UI, idprop->name))
273 return IDP_GetPropertyTypeFromGroup(idprop, ((IDProperty *)prop)->name, IDP_GROUP);
279 IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
281 StructRNA *type = ptr->type;
283 if (type && type->idproperties)
284 return type->idproperties(ptr, create);
289 bool RNA_struct_idprops_check(StructRNA *srna)
291 return (srna && srna->idproperties);
294 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
296 IDProperty *group = RNA_struct_idprops(ptr, 0);
299 return IDP_GetPropertyFromGroup(group, name);
304 static void rna_idproperty_free(PointerRNA *ptr, const char *name)
306 IDProperty *group = RNA_struct_idprops(ptr, 0);
309 IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
311 IDP_FreeFromGroup(group, idprop);
316 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
318 if (prop->magic == RNA_MAGIC) {
319 int arraylen[RNA_MAX_ARRAY_DIMENSION];
320 return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) : prop->totarraylength;
323 IDProperty *idprop = (IDProperty *)prop;
325 if (idprop->type == IDP_ARRAY)
332 static bool rna_ensure_property_array_check(PropertyRNA *prop)
334 if (prop->magic == RNA_MAGIC) {
335 return (prop->getlength || prop->totarraylength);
338 IDProperty *idprop = (IDProperty *)prop;
340 return (idprop->type == IDP_ARRAY);
344 static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int length[])
346 if (prop->magic == RNA_MAGIC) {
348 prop->getlength(ptr, length);
350 memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
353 IDProperty *idprop = (IDProperty *)prop;
355 if (idprop->type == IDP_ARRAY)
356 length[0] = idprop->len;
362 static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
364 /* this verifies if the idproperty actually matches the property
365 * description and otherwise removes it. this is to ensure that
366 * rna property access is type safe, e.g. if you defined the rna
367 * to have a certain array length you can count on that staying so */
369 switch (idprop->type) {
371 if (prop->type != PROP_COLLECTION)
375 if (rna_ensure_property_array_length(ptr, prop) != idprop->len)
378 if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
380 if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
385 if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
390 if (prop->type != PROP_FLOAT)
394 if (prop->type != PROP_STRING)
399 if (prop->type != PROP_POINTER)
409 static PropertyRNA *typemap[IDP_NUMTYPES] = {
410 (PropertyRNA *)&rna_PropertyGroupItem_string,
411 (PropertyRNA *)&rna_PropertyGroupItem_int,
412 (PropertyRNA *)&rna_PropertyGroupItem_float,
414 (PropertyRNA *)&rna_PropertyGroupItem_group,
415 (PropertyRNA *)&rna_PropertyGroupItem_id,
416 (PropertyRNA *)&rna_PropertyGroupItem_double,
417 (PropertyRNA *)&rna_PropertyGroupItem_idp_array
420 static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
421 NULL, (PropertyRNA *)&rna_PropertyGroupItem_int_array,
422 (PropertyRNA *)&rna_PropertyGroupItem_float_array,
424 (PropertyRNA *)&rna_PropertyGroupItem_collection, NULL,
425 (PropertyRNA *)&rna_PropertyGroupItem_double_array
428 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
430 /* This is quite a hack, but avoids some complexity in the API. we
431 * pass IDProperty structs as PropertyRNA pointers to the outside.
432 * We store some bytes in PropertyRNA structs that allows us to
433 * distinguish it from IDProperty structs. If it is an ID property,
434 * we look up an IDP PropertyRNA based on the type, and set the data
435 * pointer to the IDProperty. */
437 if ((*prop)->magic == RNA_MAGIC) {
438 if ((*prop)->flag & PROP_IDPROPERTY) {
439 IDProperty *idprop = rna_idproperty_find(ptr, (*prop)->identifier);
441 if (idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) {
442 IDProperty *group = RNA_struct_idprops(ptr, 0);
444 IDP_FreeFromGroup(group, idprop);
455 IDProperty *idprop = (IDProperty *)(*prop);
457 if (idprop->type == IDP_ARRAY)
458 *prop = arraytypemap[(int)(idprop->subtype)];
460 *prop = typemap[(int)(idprop->type)];
466 static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
468 /* the quick version if we don't need the idproperty */
470 if (prop->magic == RNA_MAGIC)
474 IDProperty *idprop = (IDProperty *)prop;
476 if (idprop->type == IDP_ARRAY)
477 return arraytypemap[(int)(idprop->subtype)];
479 return typemap[(int)(idprop->type)];
483 static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
485 if (prop->magic == RNA_MAGIC)
486 return prop->identifier;
488 return ((const IDProperty *)prop)->name;
491 static const char *rna_ensure_property_description(PropertyRNA *prop)
493 const char *description = NULL;
495 if (prop->magic == RNA_MAGIC)
496 description = prop->description;
498 /* attempt to get the local ID values */
499 IDProperty *idp_ui = rna_idproperty_ui(prop);
502 IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "description", IDP_STRING);
504 description = IDP_String(item);
507 if (description == NULL)
508 description = ((IDProperty *)prop)->name; /* XXX - not correct */
514 static const char *rna_ensure_property_name(const PropertyRNA *prop)
518 if (prop->magic == RNA_MAGIC)
521 name = ((const IDProperty *)prop)->name;
528 StructRNA *RNA_struct_find(const char *identifier)
530 return BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier);
533 const char *RNA_struct_identifier(const StructRNA *type)
535 return type->identifier;
538 const char *RNA_struct_ui_name(const StructRNA *type)
540 return CTX_IFACE_(type->translation_context, type->name);
543 const char *RNA_struct_ui_name_raw(const StructRNA *type)
548 int RNA_struct_ui_icon(const StructRNA *type)
556 const char *RNA_struct_ui_description(const StructRNA *type)
558 return TIP_(type->description);
561 const char *RNA_struct_ui_description_raw(const StructRNA *type)
563 return type->description;
566 const char *RNA_struct_translation_context(const StructRNA *type)
568 return type->translation_context;
571 PropertyRNA *RNA_struct_name_property(const StructRNA *type)
573 return type->nameproperty;
576 const EnumPropertyItem *RNA_struct_property_tag_defines(const StructRNA *type)
578 return type->prop_tag_defines;
581 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
583 return type->iteratorproperty;
586 StructRNA *RNA_struct_base(StructRNA *type)
592 * Use to find the subtype directly below a base-type.
594 * So if type were `RNA_SpotLamp`, `RNA_struct_base_of(type, &RNA_ID)` would return `&RNA_Lamp`.
596 const StructRNA *RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
599 if (type->base == parent_type) {
607 bool RNA_struct_is_ID(const StructRNA *type)
609 return (type->flag & STRUCT_ID) != 0;
612 bool RNA_struct_undo_check(const StructRNA *type)
614 return (type->flag & STRUCT_UNDO) != 0;
617 bool RNA_struct_idprops_register_check(const StructRNA *type)
619 return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
622 bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
624 return (type->flag & (STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_NO_IDPROPERTIES)) == 0;
628 * Whether given type implies datablock usage by IDProperties.
629 * This is used to prevent classes allowed to have IDProperties, but not datablock ones, to indirectly use some
630 * (e.g. by assigning an IDP_GROUP containing some IDP_ID pointers...).
632 bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
634 return (type->flag & (STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES | STRUCT_ID)) != 0;
637 /* remove an id-property */
638 bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
640 IDProperty *group = RNA_struct_idprops(ptr, 0);
643 IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
645 IDP_FreeFromGroup(group, idp);
653 bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
655 const StructRNA *base;
657 if (srna == &RNA_AnyType)
663 /* ptr->type is always maximally refined */
664 for (base = type; base; base = base->base)
671 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
673 if (identifier[0] == '[' && identifier[1] == '"') { /* " (dummy comment to avoid confusing some
674 * function lists in text editors) */
675 /* id prop lookup, not so common */
676 PropertyRNA *r_prop = NULL;
677 PointerRNA r_ptr; /* only support single level props */
678 if (RNA_path_resolve_property(ptr, identifier, &r_ptr, &r_prop) &&
679 (r_ptr.type == ptr->type) && (r_ptr.data == ptr->data))
685 /* most common case */
686 PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
689 if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr))
696 /* Find the property which uses the given nested struct */
697 static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
699 PropertyRNA *prop = NULL;
701 RNA_STRUCT_BEGIN (ptr, iprop)
703 /* This assumes that there can only be one user of this nested struct */
704 if (RNA_property_pointer_type(ptr, iprop) == srna) {
714 bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
716 /* note, prop_test could be freed memory, only use for comparison */
718 /* validate the RNA is ok */
719 PropertyRNA *iterprop;
722 iterprop = RNA_struct_iterator_property(ptr->type);
724 RNA_PROP_BEGIN (ptr, itemptr, iterprop)
726 /* PropertyRNA *prop = itemptr.data; */
727 if (prop_test == (PropertyRNA *)itemptr.data) {
737 unsigned int RNA_struct_count_properties(StructRNA *srna)
739 PointerRNA struct_ptr;
740 unsigned int counter = 0;
742 RNA_pointer_create(NULL, srna, NULL, &struct_ptr);
744 RNA_STRUCT_BEGIN (&struct_ptr, prop)
754 /* low level direct access to type->properties, note this ignores parent classes so should be used with care */
755 const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
757 return &srna->cont.properties;
760 PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
762 return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
765 FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
770 for (type = srna; type; type = type->base) {
771 func = (FunctionRNA *)BLI_findstring_ptr(&type->functions, identifier, offsetof(FunctionRNA, identifier));
778 /* funcitonal but slow */
781 PropertyRNA *iterprop;
784 RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr);
785 iterprop = RNA_struct_find_property(&tptr, "functions");
789 RNA_PROP_BEGIN (&tptr, funcptr, iterprop)
791 if (STREQ(identifier, RNA_function_identifier(funcptr.data))) {
802 const ListBase *RNA_struct_type_functions(StructRNA *srna)
804 return &srna->functions;
807 StructRegisterFunc RNA_struct_register(StructRNA *type)
812 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
817 } while ((type = type->base));
822 void **RNA_struct_instance(PointerRNA *ptr)
824 StructRNA *type = ptr->type;
828 return type->instance(ptr);
829 } while ((type = type->base));
834 void *RNA_struct_py_type_get(StructRNA *srna)
836 return srna->py_type;
839 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
841 srna->py_type = py_type;
844 void *RNA_struct_blender_type_get(StructRNA *srna)
846 return srna->blender_type;
849 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
851 srna->blender_type = blender_type;
854 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
856 PropertyRNA *nameprop;
858 if (ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
859 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
865 * Use when registering structs with the #STRUCT_PUBLIC_NAMESPACE flag.
867 bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
869 const StructRNA *srna_exists = RNA_struct_find(identifier);
870 if (UNLIKELY(srna_exists != NULL)) {
871 /* Use comprehensive string construction since this is such a rare occurrence
872 * and information here may cut down time troubleshooting. */
873 DynStr *dynstr = BLI_dynstr_new();
874 BLI_dynstr_appendf(dynstr, "Type identifier '%s' is already in use: '", identifier);
875 BLI_dynstr_append(dynstr, srna_exists->identifier);
877 if (srna_exists->base) {
878 for (const StructRNA *base = srna_exists->base; base; base = base->base) {
879 BLI_dynstr_append(dynstr, "(");
880 BLI_dynstr_append(dynstr, base->identifier);
884 BLI_dynstr_append(dynstr, ")");
887 BLI_dynstr_append(dynstr, "'.");
888 char *result = BLI_dynstr_get_cstring(dynstr);
889 BLI_dynstr_free(dynstr);
890 BKE_report(reports, RPT_ERROR, result);
899 bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const char *identifier, const char *sep)
901 const int len_sep = strlen(sep);
902 const int len_id = strlen(identifier);
903 const char *p = strstr(identifier, sep);
904 /* TODO: make error, for now warning until add-ons update. */
906 const int report_level = RPT_WARNING;
907 const bool failure = true;
909 const int report_level = RPT_ERROR;
910 const bool failure = false;
912 if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) {
913 BKE_reportf(reports, report_level, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep);
917 const char *c, *start, *end, *last;
921 for (c = start; c != end; c++) {
922 if (((*c >= 'A' && *c <= 'Z') ||
923 ((c != start) && (*c >= '0' && *c <= '9')) ||
924 ((c != start) && (c != last) && (*c == '_'))) == 0)
926 BKE_reportf(reports, report_level, "'%s' doesn't have upper case alpha-numeric prefix", identifier);
932 end = identifier + len_id;
934 for (c = start; c != end; c++) {
935 if (((*c >= 'A' && *c <= 'Z') ||
936 (*c >= 'a' && *c <= 'z') ||
937 (*c >= '0' && *c <= '9') ||
938 ((c != start) && (c != last) && (*c == '_'))) == 0)
940 BKE_reportf(reports, report_level, "'%s' doesn't have an alpha-numeric suffix", identifier);
947 /* Property Information */
949 const char *RNA_property_identifier(PropertyRNA *prop)
951 return rna_ensure_property_identifier(prop);
954 const char *RNA_property_description(PropertyRNA *prop)
956 return TIP_(rna_ensure_property_description(prop));
959 PropertyType RNA_property_type(PropertyRNA *prop)
961 return rna_ensure_property(prop)->type;
964 PropertySubType RNA_property_subtype(PropertyRNA *prop)
966 return rna_ensure_property(prop)->subtype;
969 PropertyUnit RNA_property_unit(PropertyRNA *prop)
971 return RNA_SUBTYPE_UNIT(rna_ensure_property(prop)->subtype);
974 int RNA_property_flag(PropertyRNA *prop)
976 return rna_ensure_property(prop)->flag;
980 * Get the tags set for \a prop as int bitfield.
981 * \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this
982 * in debug builds (to avoid performance issues in non-debug builds), which should be
983 * the only way to set tags. Hence, at this point we assume the tag bitfield to be valid.
985 int RNA_property_tags(PropertyRNA *prop)
987 return rna_ensure_property(prop)->tags;
990 bool RNA_property_builtin(PropertyRNA *prop)
992 return (rna_ensure_property(prop)->flag_internal & PROP_INTERN_BUILTIN) != 0;
995 void *RNA_property_py_data_get(PropertyRNA *prop)
997 return prop->py_data;
1000 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
1002 return rna_ensure_property_array_length(ptr, prop);
1005 bool RNA_property_array_check(PropertyRNA *prop)
1007 return rna_ensure_property_array_check(prop);
1010 /* used by BPY to make an array from the python object */
1011 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
1013 PropertyRNA *rprop = rna_ensure_property(prop);
1016 rna_ensure_property_multi_array_length(ptr, prop, length);
1018 return rprop->arraydimension;
1021 /* Return the size of Nth dimension. */
1022 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
1024 int len[RNA_MAX_ARRAY_DIMENSION];
1026 rna_ensure_property_multi_array_length(ptr, prop, len);
1031 char RNA_property_array_item_char(PropertyRNA *prop, int index)
1033 const char *vectoritem = "XYZW";
1034 const char *quatitem = "WXYZ";
1035 const char *coloritem = "RGBA";
1036 PropertySubType subtype = rna_ensure_property(prop)->subtype;
1038 BLI_assert(index >= 0);
1040 /* get string to use for array index */
1041 if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1042 return quatitem[index];
1044 else if ((index < 4) && ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
1045 PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
1047 return vectoritem[index];
1049 else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1050 return coloritem[index];
1056 int RNA_property_array_item_index(PropertyRNA *prop, char name)
1058 PropertySubType subtype = rna_ensure_property(prop)->subtype;
1060 /* get index based on string name/alias */
1061 /* maybe a function to find char index in string would be better than all the switches */
1062 if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1074 else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
1075 PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
1088 else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1105 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
1107 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1108 int softmin, softmax;
1110 if (prop->magic != RNA_MAGIC) {
1111 /* attempt to get the local ID values */
1112 IDProperty *idp_ui = rna_idproperty_ui(prop);
1117 item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
1118 *hardmin = item ? IDP_Int(item) : INT_MIN;
1120 item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
1121 *hardmax = item ? IDP_Int(item) : INT_MAX;
1131 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1133 else if (iprop->range_ex) {
1137 iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1140 *hardmin = iprop->hardmin;
1141 *hardmax = iprop->hardmax;
1145 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
1147 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1148 int hardmin, hardmax;
1150 if (prop->magic != RNA_MAGIC) {
1151 /* attempt to get the local ID values */
1152 IDProperty *idp_ui = rna_idproperty_ui(prop);
1157 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
1158 *softmin = item ? IDP_Int(item) : INT_MIN;
1160 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
1161 *softmax = item ? IDP_Int(item) : INT_MAX;
1163 item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
1164 *step = item ? IDP_Int(item) : 1;
1170 *softmin = iprop->softmin;
1171 *softmax = iprop->softmax;
1177 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1179 *softmin = max_ii(*softmin, hardmin);
1180 *softmax = min_ii(*softmax, hardmax);
1182 else if (iprop->range_ex) {
1186 iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1188 *softmin = max_ii(*softmin, hardmin);
1189 *softmax = min_ii(*softmax, hardmax);
1192 *step = iprop->step;
1195 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1197 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1198 float softmin, softmax;
1200 if (prop->magic != RNA_MAGIC) {
1201 /* attempt to get the local ID values */
1202 IDProperty *idp_ui = rna_idproperty_ui(prop);
1207 item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
1208 *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1210 item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1211 *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1218 *hardmin = -FLT_MAX;
1221 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1223 else if (fprop->range_ex) {
1224 *hardmin = -FLT_MAX;
1227 fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1230 *hardmin = fprop->hardmin;
1231 *hardmax = fprop->hardmax;
1235 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax,
1236 float *step, float *precision)
1238 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1239 float hardmin, hardmax;
1241 if (prop->magic != RNA_MAGIC) {
1242 /* attempt to get the local ID values */
1243 IDProperty *idp_ui = rna_idproperty_ui(prop);
1248 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1249 *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1251 item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1252 *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1254 item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1255 *step = item ? (float)IDP_Double(item) : 1.0f;
1257 item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1258 *precision = item ? (float)IDP_Double(item) : 3.0f;
1264 *softmin = fprop->softmin;
1265 *softmax = fprop->softmax;
1271 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1273 *softmin = max_ff(*softmin, hardmin);
1274 *softmax = min_ff(*softmax, hardmax);
1276 else if (fprop->range_ex) {
1280 fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1282 *softmin = max_ff(*softmin, hardmin);
1283 *softmax = min_ff(*softmax, hardmax);
1286 *step = fprop->step;
1287 *precision = (float)fprop->precision;
1290 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1294 RNA_property_float_range(ptr, prop, &min, &max);
1300 else if (*value > max) {
1309 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1313 RNA_property_int_range(ptr, prop, &min, &max);
1319 else if (*value > max) {
1328 /* this is the max length including \0 terminator.
1329 * '0' used when their is no maximum */
1330 int RNA_property_string_maxlength(PropertyRNA *prop)
1332 StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1333 return sprop->maxlength;
1336 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1338 prop = rna_ensure_property(prop);
1340 if (prop->type == PROP_POINTER) {
1341 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1344 return pprop->typef(ptr);
1345 else if (pprop->type)
1348 else if (prop->type == PROP_COLLECTION) {
1349 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1351 if (cprop->item_type)
1352 return cprop->item_type;
1354 /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1356 return &RNA_UnknownType;
1359 int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1361 prop = rna_ensure_property(prop);
1363 if (prop->type == PROP_POINTER) {
1364 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1367 if (rna_idproperty_check(&prop, ptr)) {
1368 return ((PropPointerPollFuncPy) pprop->poll)(ptr, *value, prop);
1371 return pprop->poll(ptr, *value);
1378 printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
1382 /* Reuse for dynamic types */
1383 const EnumPropertyItem DummyRNA_NULL_items[] = {
1384 {0, NULL, 0, NULL, NULL}
1387 /* Reuse for dynamic types with default value */
1388 const EnumPropertyItem DummyRNA_DEFAULT_items[] = {
1389 {0, "DEFAULT", 0, "Default", ""},
1390 {0, NULL, 0, NULL, NULL}
1393 void RNA_property_enum_items_ex(
1394 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const bool use_static,
1395 const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1397 EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1401 if (!use_static && eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1402 const EnumPropertyItem *item;
1404 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1405 item = eprop->itemf(NULL, ptr, prop, r_free);
1407 item = eprop->itemf(C, ptr, prop, r_free);
1409 /* any callbacks returning NULL should be fixed */
1410 BLI_assert(item != NULL);
1414 for (tot = 0; item[tot].identifier; tot++) {
1423 *r_item = eprop->item;
1425 *r_totitem = eprop->totitem;
1429 void RNA_property_enum_items(
1430 bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1431 const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1433 RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free);
1436 #ifdef WITH_INTERNATIONAL
1437 static void property_enum_translate(
1438 PropertyRNA *prop, EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1440 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1443 /* Note: Only do those tests once, and then use BLT_pgettext. */
1444 bool do_iface = BLT_translate_iface();
1445 bool do_tooltip = BLT_translate_tooltips();
1446 EnumPropertyItem *nitem;
1448 if (!(do_iface || do_tooltip))
1455 const EnumPropertyItem *item = *r_item;
1463 for (tot = 0; item[tot].identifier; tot++) {
1468 nitem = MEM_mallocN(sizeof(EnumPropertyItem) * (tot + 1), "enum_items_gettexted");
1469 memcpy(nitem, item, sizeof(EnumPropertyItem) * (tot + 1));
1474 for (i = 0; nitem[i].identifier; i++) {
1475 if (nitem[i].name && do_iface) {
1476 nitem[i].name = BLT_pgettext(prop->translation_context, nitem[i].name);
1478 if (nitem[i].description && do_tooltip) {
1479 nitem[i].description = BLT_pgettext(NULL, nitem[i].description);
1488 void RNA_property_enum_items_gettexted(
1489 bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1490 const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1492 RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
1494 #ifdef WITH_INTERNATIONAL
1495 /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory
1496 * so allow the exception (callers are creating new arrays in this case). */
1497 property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free);
1501 void RNA_property_enum_items_gettexted_all(
1502 bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1503 const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1505 EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1506 int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
1507 /* first return all items */
1508 EnumPropertyItem *item_array = MEM_mallocN(mem_size, "enum_gettext_all");
1510 memcpy(item_array, eprop->item, mem_size);
1513 *r_totitem = eprop->totitem;
1516 if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1517 const EnumPropertyItem *item;
1521 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1522 item = eprop->itemf(NULL, ptr, prop, &free);
1524 item = eprop->itemf(C, ptr, prop, &free);
1526 /* any callbacks returning NULL should be fixed */
1527 BLI_assert(item != NULL);
1529 for (i = 0; i < eprop->totitem; i++) {
1530 bool exists = false;
1533 /* items that do not exist on list are returned, but have their names/identifiers NULLed out */
1534 for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
1535 if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
1542 item_array[i].name = NULL;
1543 item_array[i].identifier = "";
1548 MEM_freeN((void *)item);
1552 #ifdef WITH_INTERNATIONAL
1553 property_enum_translate(prop, &item_array, r_totitem, r_free);
1555 *r_item = item_array;
1558 bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
1560 const EnumPropertyItem *item;
1564 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1567 const int i = RNA_enum_from_identifier(item, identifier);
1569 *r_value = item[i].value;
1577 MEM_freeN((void *)item);
1586 bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
1588 const int i = RNA_enum_from_value(item, value);
1590 *r_identifier = item[i].identifier;
1598 int RNA_enum_bitflag_identifiers(const EnumPropertyItem *item, const int value, const char **r_identifier)
1601 for (; item->identifier; item++) {
1602 if (item->identifier[0] && item->value & value) {
1603 r_identifier[index++] = item->identifier;
1606 r_identifier[index] = NULL;
1610 bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
1612 const int i = RNA_enum_from_value(item, value);
1614 *r_name = item[i].name;
1622 bool RNA_enum_description(const EnumPropertyItem *item, const int value, const char **r_description)
1624 const int i = RNA_enum_from_value(item, value);
1626 *r_description = item[i].description;
1634 int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
1637 for (; item->identifier; item++, i++) {
1638 if (item->identifier[0] && STREQ(item->identifier, identifier)) {
1645 int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
1648 for (; item->identifier; item++, i++) {
1649 if (item->identifier[0] && item->value == value) {
1656 unsigned int RNA_enum_items_count(const EnumPropertyItem *item)
1660 while (item->identifier) {
1668 bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1669 const char **identifier)
1671 const EnumPropertyItem *item = NULL;
1674 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1677 result = RNA_enum_identifier(item, value, identifier);
1679 MEM_freeN((void *)item);
1686 bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1688 const EnumPropertyItem *item = NULL;
1691 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1694 result = RNA_enum_name(item, value, name);
1696 MEM_freeN((void *)item);
1704 bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1708 result = RNA_property_enum_name(C, ptr, prop, value, name);
1711 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1712 if (BLT_translate_iface()) {
1713 *name = BLT_pgettext(prop->translation_context, *name);
1721 bool RNA_property_enum_item_from_value(
1722 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1723 EnumPropertyItem *r_item)
1725 const EnumPropertyItem *item = NULL;
1728 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1730 const int i = RNA_enum_from_value(item, value);
1742 MEM_freeN((void *)item);
1750 bool RNA_property_enum_item_from_value_gettexted(
1751 bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1752 EnumPropertyItem *r_item)
1756 result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
1758 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1759 if (BLT_translate_iface()) {
1760 r_item->name = BLT_pgettext(prop->translation_context, r_item->name);
1767 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1768 const char **identifier)
1770 const EnumPropertyItem *item = NULL;
1773 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1776 result = RNA_enum_bitflag_identifiers(item, value, identifier);
1778 MEM_freeN((void *)item);
1785 const char *RNA_property_ui_name(PropertyRNA *prop)
1787 return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
1790 const char *RNA_property_ui_name_raw(PropertyRNA *prop)
1792 return rna_ensure_property_name(prop);
1795 const char *RNA_property_ui_description(PropertyRNA *prop)
1797 return TIP_(rna_ensure_property_description(prop));
1800 const char *RNA_property_ui_description_raw(PropertyRNA *prop)
1802 return rna_ensure_property_description(prop);
1805 const char *RNA_property_translation_context(PropertyRNA *_prop)
1807 PropertyRNA *prop = rna_ensure_property(_prop);
1808 return prop->translation_context;
1811 int RNA_property_ui_icon(PropertyRNA *prop)
1813 return rna_ensure_property(prop)->icon;
1816 bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1818 ID *id = ptr->id.data;
1820 const char *dummy_info;
1822 prop = rna_ensure_property(prop);
1823 flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
1825 return ((flag & PROP_EDITABLE) &&
1826 (flag & PROP_REGISTER) == 0 &&
1827 (!id || ((!ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)) &&
1828 (!id->override_static || (prop->flag & PROP_OVERRIDABLE_STATIC)))));
1832 * Version of #RNA_property_editable that tries to return additional info in \a r_info that can be exposed in UI.
1834 bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
1836 ID *id = ptr->id.data;
1839 prop = rna_ensure_property(prop);
1843 if (prop->editable) {
1844 flag = prop->editable(ptr, r_info);
1848 if ((flag & PROP_EDITABLE) == 0 || (flag & PROP_REGISTER)) {
1849 *r_info = "This property is for internal use only and can't be edited.";
1853 /* property from linked data-block */
1855 if (ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
1856 if (!(*r_info)[0]) {
1857 *r_info = "Can't edit this property from a linked data-block.";
1861 if (id->override_static != NULL && (prop->flag & PROP_OVERRIDABLE_STATIC) == 0) {
1862 if (!(*r_info)[0]) {
1863 *r_info = "Can't edit this property from an override data-block.";
1869 return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
1872 bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
1875 const char *dummy_info;
1877 prop = rna_ensure_property(prop);
1878 flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
1879 return (flag & PROP_EDITABLE) != 0;
1882 /* same as RNA_property_editable(), except this checks individual items in an array */
1883 bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1888 BLI_assert(index >= 0);
1890 prop = rna_ensure_property(prop);
1894 if (prop->editable) {
1895 const char *dummy_info;
1896 flag &= prop->editable(ptr, &dummy_info);
1899 if (prop->itemeditable)
1900 flag &= prop->itemeditable(ptr, index);
1904 return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION));
1907 bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1909 /* check that base ID-block can support animation data */
1910 if (!id_can_have_animdata(ptr->id.data))
1913 prop = rna_ensure_property(prop);
1915 if (!(prop->flag & PROP_ANIMATABLE))
1918 return (prop->flag & PROP_EDITABLE) != 0;
1921 bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
1924 bool driven, special;
1929 if (RNA_property_array_check(prop))
1930 len = RNA_property_array_length(ptr, prop);
1932 for (index = 0; index < len; index++) {
1933 if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special))
1940 /* this function is to check if its possible to create a valid path from the ID
1941 * its slow so don't call in a loop */
1942 bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
1944 char *path = RNA_path_from_ID_to_property(ptr, prop);
1950 PropertyRNA *r_prop;
1952 RNA_id_pointer_create(ptr->id.data, &id_ptr);
1953 if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
1954 ret = (prop == r_prop);
1963 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1965 const bool is_rna = (prop->magic == RNA_MAGIC);
1966 prop = rna_ensure_property(prop);
1970 /* ideally no context would be needed for update, but there's some
1971 * parts of the code that need it still, so we have this exception */
1972 if (prop->flag & PROP_CONTEXT_UPDATE) {
1974 if ((prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) == PROP_CONTEXT_PROPERTY_UPDATE) {
1975 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
1978 ((ContextUpdateFunc)prop->update)(C, ptr);
1983 prop->update(bmain, scene, ptr);
1987 WM_main_add_notifier(prop->noteflag, ptr->id.data);
1989 /* if C is NULL, we're updating from animation.
1990 * avoid slow-down from f-curves by not publishing (for now). */
1992 struct wmMsgBus *mbus = CTX_wm_message_bus(C);
1993 /* we could add NULL check, for now don't */
1994 WM_msg_publish_rna(mbus, ptr, prop);
1999 if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
2000 /* WARNING! This is so property drivers update the display!
2001 * not especially nice */
2002 DEG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
2003 WM_main_add_notifier(NC_WINDOW, NULL);
2004 /* Not nice as well, but the only way to make sure material preview
2005 * is updated with custom nodes.
2007 if ((prop->flag & PROP_IDPROPERTY) != 0 &&
2008 (ptr->id.data != NULL) &&
2009 (GS(((ID *)ptr->id.data)->name) == ID_NT))
2011 WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
2016 /* must keep in sync with 'rna_property_update'
2017 * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
2018 * but this isn't likely to be a performance problem. */
2019 bool RNA_property_update_check(PropertyRNA *prop)
2021 return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
2024 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
2026 rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
2029 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2031 rna_property_update(NULL, bmain, scene, ptr, prop);
2035 /* RNA Updates Cache ------------------------ */
2036 /* Overview of RNA Update cache system:
2038 * RNA Update calls need to be cached in order to maintain reasonable performance
2039 * of the animation system (i.e. maintaining a somewhat interactive framerate)
2040 * while still allowing updates to be called (necessary in particular for modifier
2041 * property updates to actually work).
2043 * The cache is structured with a dual-layer structure
2044 * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
2045 * and most updates end up using just that anyways)
2046 * - L2 = Update functions to be called on those PointerRNA's
2050 typedef struct tRnaUpdateCacheElem {
2051 struct tRnaUpdateCacheElem *next, *prev;
2053 PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */
2054 ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */
2055 } tRnaUpdateCacheElem;
2057 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
2058 static ListBase rna_updates_cache = {NULL, NULL};
2060 /* ........................... */
2062 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
2064 const bool is_rna = (prop->magic == RNA_MAGIC);
2065 tRnaUpdateCacheElem *uce = NULL;
2066 UpdateFunc fn = NULL;
2073 prop = rna_ensure_property(prop);
2075 /* we can only handle update calls with no context args for now (makes animsys updates easier) */
2076 if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
2080 /* find cache element for which key matches... */
2081 for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2082 /* just match by id only for now, since most update calls that we'll encounter only really care about this */
2083 /* TODO: later, the cache might need to have some nesting on L1 to cope better
2084 * with these problems + some tagging to indicate we need this */
2085 if (uce->ptr.id.data == ptr->id.data)
2089 /* create new instance */
2090 uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
2091 BLI_addtail(&rna_updates_cache, uce);
2094 RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
2097 /* check on the update func */
2098 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2099 /* stop on match - function already cached */
2103 /* else... if still here, we need to add it */
2104 BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
2107 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
2109 tRnaUpdateCacheElem *uce;
2111 /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
2113 /* execute the cached updates */
2114 for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2117 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2118 UpdateFunc fn = (UpdateFunc)ld->data;
2119 fn(bmain, scene, &uce->ptr);
2124 void RNA_property_update_cache_free(void)
2126 tRnaUpdateCacheElem *uce, *ucn;
2128 for (uce = rna_updates_cache.first; uce; uce = ucn) {
2132 BLI_freelistN(&uce->L2Funcs);
2135 BLI_freelinkN(&rna_updates_cache, uce);
2139 /* ---------------------------------------------------------------------- */
2143 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
2145 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2149 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2150 BLI_assert(RNA_property_array_check(prop) == false);
2152 if ((idprop = rna_idproperty_check(&prop, ptr)))
2153 value = IDP_Int(idprop);
2154 else if (bprop->get)
2155 value = bprop->get(ptr);
2156 else if (bprop->get_ex)
2157 value = bprop->get_ex(ptr, prop);
2159 value = bprop->defaultvalue;
2161 BLI_assert(ELEM(value, false, true));
2166 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2168 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2171 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2172 BLI_assert(RNA_property_array_check(prop) == false);
2173 BLI_assert(ELEM(value, false, true));
2175 /* just in case other values are passed */
2176 if (value) value = 1;
2178 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2179 IDP_Int(idprop) = value;
2180 rna_idproperty_touch(idprop);
2182 else if (bprop->set) {
2183 bprop->set(ptr, value);
2185 else if (bprop->set_ex) {
2186 bprop->set_ex(ptr, prop, value);
2188 else if (prop->flag & PROP_EDITABLE) {
2189 IDPropertyTemplate val = {0};
2194 group = RNA_struct_idprops(ptr, 1);
2196 IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2200 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2202 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2205 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2206 BLI_assert(RNA_property_array_check(prop) != false);
2208 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2209 if (prop->arraydimension == 0)
2210 values[0] = RNA_property_boolean_get(ptr, prop);
2212 memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2214 else if (prop->arraydimension == 0)
2215 values[0] = RNA_property_boolean_get(ptr, prop);
2216 else if (bprop->getarray)
2217 bprop->getarray(ptr, values);
2218 else if (bprop->getarray_ex)
2219 bprop->getarray_ex(ptr, prop, values);
2220 else if (bprop->defaultarray)
2221 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
2223 memset(values, 0, sizeof(int) * prop->totarraylength);
2226 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2228 int tmp[RNA_MAX_ARRAY_LENGTH];
2229 int len = rna_ensure_property_array_length(ptr, prop);
2232 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2233 BLI_assert(RNA_property_array_check(prop) != false);
2234 BLI_assert(index >= 0);
2235 BLI_assert(index < len);
2237 if (len <= RNA_MAX_ARRAY_LENGTH) {
2238 RNA_property_boolean_get_array(ptr, prop, tmp);
2244 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2245 RNA_property_boolean_get_array(ptr, prop, tmparray);
2246 value = tmparray[index];
2247 MEM_freeN(tmparray);
2250 BLI_assert(ELEM(value, false, true));
2255 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2257 BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2260 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2261 BLI_assert(RNA_property_array_check(prop) != false);
2263 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2264 if (prop->arraydimension == 0)
2265 IDP_Int(idprop) = values[0];
2267 memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2269 rna_idproperty_touch(idprop);
2271 else if (prop->arraydimension == 0)
2272 RNA_property_boolean_set(ptr, prop, values[0]);
2273 else if (bprop->setarray)
2274 bprop->setarray(ptr, values);
2275 else if (bprop->setarray_ex)
2276 bprop->setarray_ex(ptr, prop, values);
2277 else if (prop->flag & PROP_EDITABLE) {
2278 IDPropertyTemplate val = {0};
2281 val.array.len = prop->totarraylength;
2282 val.array.type = IDP_INT;
2284 group = RNA_struct_idprops(ptr, 1);
2286 idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2287 IDP_AddToGroup(group, idprop);
2288 memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2293 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2295 int tmp[RNA_MAX_ARRAY_LENGTH];
2296 int len = rna_ensure_property_array_length(ptr, prop);
2298 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2299 BLI_assert(RNA_property_array_check(prop) != false);
2300 BLI_assert(index >= 0);
2301 BLI_assert(index < len);
2302 BLI_assert(ELEM(value, false, true));
2304 if (len <= RNA_MAX_ARRAY_LENGTH) {
2305 RNA_property_boolean_get_array(ptr, prop, tmp);
2307 RNA_property_boolean_set_array(ptr, prop, tmp);
2312 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2313 RNA_property_boolean_get_array(ptr, prop, tmparray);
2314 tmparray[index] = value;
2315 RNA_property_boolean_set_array(ptr, prop, tmparray);
2316 MEM_freeN(tmparray);
2320 int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2322 BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2324 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2325 BLI_assert(RNA_property_array_check(prop) == false);
2326 BLI_assert(ELEM(bprop->defaultvalue, false, true));
2328 return bprop->defaultvalue;
2331 void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2333 BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2335 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2336 BLI_assert(RNA_property_array_check(prop) != false);
2338 if (prop->arraydimension == 0)
2339 values[0] = bprop->defaultvalue;
2340 else if (bprop->defaultarray)
2341 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
2343 memset(values, 0, sizeof(int) * prop->totarraylength);
2346 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2348 int tmp[RNA_MAX_ARRAY_LENGTH];
2349 int len = rna_ensure_property_array_length(ptr, prop);
2351 BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2352 BLI_assert(RNA_property_array_check(prop) != false);
2353 BLI_assert(index >= 0);
2354 BLI_assert(index < prop->totarraylength);
2356 if (len <= RNA_MAX_ARRAY_LENGTH) {
2357 RNA_property_boolean_get_default_array(ptr, prop, tmp);
2361 int *tmparray, value;
2363 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2364 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
2365 value = tmparray[index];
2366 MEM_freeN(tmparray);
2372 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
2374 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2377 BLI_assert(RNA_property_type(prop) == PROP_INT);
2378 BLI_assert(RNA_property_array_check(prop) == false);
2380 if ((idprop = rna_idproperty_check(&prop, ptr)))
2381 return IDP_Int(idprop);
2382 else if (iprop->get)
2383 return iprop->get(ptr);
2384 else if (iprop->get_ex)
2385 return iprop->get_ex(ptr, prop);
2387 return iprop->defaultvalue;
2390 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2392 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2395 BLI_assert(RNA_property_type(prop) == PROP_INT);
2396 BLI_assert(RNA_property_array_check(prop) == false);
2397 /* useful to check on bad values but set function should clamp */
2398 /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
2400 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2401 RNA_property_int_clamp(ptr, prop, &value);
2402 IDP_Int(idprop) = value;
2403 rna_idproperty_touch(idprop);
2405 else if (iprop->set)
2406 iprop->set(ptr, value);
2407 else if (iprop->set_ex)
2408 iprop->set_ex(ptr, prop, value);
2409 else if (prop->flag & PROP_EDITABLE) {
2410 IDPropertyTemplate val = {0};
2413 RNA_property_int_clamp(ptr, prop, &value);
2417 group = RNA_struct_idprops(ptr, 1);
2419 IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2423 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2425 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2428 BLI_assert(RNA_property_type(prop) == PROP_INT);
2429 BLI_assert(RNA_property_array_check(prop) != false);
2431 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2432 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2433 if (prop->arraydimension == 0)
2434 values[0] = RNA_property_int_get(ptr, prop);
2436 memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2438 else if (prop->arraydimension == 0)
2439 values[0] = RNA_property_int_get(ptr, prop);
2440 else if (iprop->getarray)
2441 iprop->getarray(ptr, values);
2442 else if (iprop->getarray_ex)
2443 iprop->getarray_ex(ptr, prop, values);
2444 else if (iprop->defaultarray)
2445 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2447 memset(values, 0, sizeof(int) * prop->totarraylength);
2450 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
2452 const int array_len = RNA_property_array_length(ptr, prop);
2454 if (array_len <= 0) {
2458 else if (array_len == 1) {
2459 RNA_property_int_get_array(ptr, prop, values);
2460 values[1] = values[0];
2467 if (array_len > 32) {
2468 arr = MEM_mallocN(sizeof(int) * array_len, __func__);
2474 RNA_property_int_get_array(ptr, prop, arr);
2475 values[0] = values[1] = arr[0];
2476 for (i = 1; i < array_len; i++) {
2477 values[0] = MIN2(values[0], arr[i]);
2478 values[1] = MAX2(values[1], arr[i]);
2481 if (arr != arr_stack) {
2487 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2489 int tmp[RNA_MAX_ARRAY_LENGTH];
2490 int len = rna_ensure_property_array_length(ptr, prop);
2492 BLI_assert(RNA_property_type(prop) == PROP_INT);
2493 BLI_assert(RNA_property_array_check(prop) != false);
2494 BLI_assert(index >= 0);
2495 BLI_assert(index < len);
2497 if (len <= RNA_MAX_ARRAY_LENGTH) {
2498 RNA_property_int_get_array(ptr, prop, tmp);
2502 int *tmparray, value;
2504 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2505 RNA_property_int_get_array(ptr, prop, tmparray);
2506 value = tmparray[index];
2507 MEM_freeN(tmparray);
2513 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2515 IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2518 BLI_assert(RNA_property_type(prop) == PROP_INT);
2519 BLI_assert(RNA_property_array_check(prop) != false);
2521 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2522 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2523 if (prop->arraydimension == 0)
2524 IDP_Int(idprop) = values[0];
2526 memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2528 rna_idproperty_touch(idprop);
2530 else if (prop->arraydimension == 0)
2531 RNA_property_int_set(ptr, prop, values[0]);
2532 else if (iprop->setarray)
2533 iprop->setarray(ptr, values);
2534 else if (iprop->setarray_ex)
2535 iprop->setarray_ex(ptr, prop, values);
2536 else if (prop->flag & PROP_EDITABLE) {
2537 IDPropertyTemplate val = {0};
2540 /* TODO: RNA_property_int_clamp_array(ptr, prop, &value); */
2542 val.array.len = prop->totarraylength;
2543 val.array.type = IDP_INT;
2545 group = RNA_struct_idprops(ptr, 1);
2547 idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2548 IDP_AddToGroup(group, idprop);
2549 memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2554 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2556 int tmp[RNA_MAX_ARRAY_LENGTH];
2557 int len = rna_ensure_property_array_length(ptr, prop);
2559 BLI_assert(RNA_property_type(prop) == PROP_INT);
2560 BLI_assert(RNA_property_array_check(prop) != false);
2561 BLI_assert(index >= 0);
2562 BLI_assert(index < len);
2564 if (len <= RNA_MAX_ARRAY_LENGTH) {
2565 RNA_property_int_get_array(ptr, prop, tmp);
2567 RNA_property_int_set_array(ptr, prop, tmp);
2572 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2573 RNA_property_int_get_array(ptr, prop, tmparray);
2574 tmparray[index] = value;
2575 RNA_property_int_set_array(ptr, prop, tmparray);
2576 MEM_freeN(tmparray);
2580 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2582 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2583 return iprop->defaultvalue;
2586 void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2588 IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2590 BLI_assert(RNA_property_type(prop) == PROP_INT);
2591 BLI_assert(RNA_property_array_check(prop) != false);
2593 if (prop->arraydimension == 0)
2594 values[0] = iprop->defaultvalue;
2595 else if (iprop->defaultarray)
2596 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2598 memset(values, 0, sizeof(int) * prop->totarraylength);
2601 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2603 int tmp[RNA_MAX_ARRAY_LENGTH];
2604 int len = rna_ensure_property_array_length(ptr, prop);
2606 BLI_assert(RNA_property_type(prop) == PROP_INT);
2607 BLI_assert(RNA_property_array_check(prop) != false);
2608 BLI_assert(index >= 0);
2609 BLI_assert(index < prop->totarraylength);
2611 if (len <= RNA_MAX_ARRAY_LENGTH) {
2612 RNA_property_int_get_default_array(ptr, prop, tmp);
2616 int *tmparray, value;
2618 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2619 RNA_property_int_get_default_array(ptr, prop, tmparray);
2620 value = tmparray[index];
2621 MEM_freeN(tmparray);
2627 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
2629 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2632 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2633 BLI_assert(RNA_property_array_check(prop) == false);
2635 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2636 if (idprop->type == IDP_FLOAT)
2637 return IDP_Float(idprop);
2639 return (float)IDP_Double(idprop);
2641 else if (fprop->get)
2642 return fprop->get(ptr);
2643 else if (fprop->get_ex)
2644 return fprop->get_ex(ptr, prop);
2646 return fprop->defaultvalue;
2649 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
2651 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2654 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2655 BLI_assert(RNA_property_array_check(prop) == false);
2656 /* useful to check on bad values but set function should clamp */
2657 /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
2659 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2660 RNA_property_float_clamp(ptr, prop, &value);
2661 if (idprop->type == IDP_FLOAT)
2662 IDP_Float(idprop) = value;
2664 IDP_Double(idprop) = value;
2666 rna_idproperty_touch(idprop);
2668 else if (fprop->set) {
2669 fprop->set(ptr, value);
2671 else if (fprop->set_ex) {
2672 fprop->set_ex(ptr, prop, value);
2674 else if (prop->flag & PROP_EDITABLE) {
2675 IDPropertyTemplate val = {0};
2678 RNA_property_float_clamp(ptr, prop, &value);
2682 group = RNA_struct_idprops(ptr, 1);
2684 IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
2688 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
2690 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2694 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2695 BLI_assert(RNA_property_array_check(prop) != false);
2697 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2698 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2699 if (prop->arraydimension == 0)
2700 values[0] = RNA_property_float_get(ptr, prop);
2701 else if (idprop->subtype == IDP_FLOAT) {
2702 memcpy(values, IDP_Array(idprop), sizeof(float) * idprop->len);
2705 for (i = 0; i < idprop->len; i++)
2706 values[i] = (float)(((double *)IDP_Array(idprop))[i]);
2709 else if (prop->arraydimension == 0)
2710 values[0] = RNA_property_float_get(ptr, prop);
2711 else if (fprop->getarray)
2712 fprop->getarray(ptr, values);
2713 else if (fprop->getarray_ex)
2714 fprop->getarray_ex(ptr, prop, values);
2715 else if (fprop->defaultarray)
2716 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2718 memset(values, 0, sizeof(float) * prop->totarraylength);
2721 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
2723 const int array_len = RNA_property_array_length(ptr, prop);
2725 if (array_len <= 0) {
2729 else if (array_len == 1) {
2730 RNA_property_float_get_array(ptr, prop, values);
2731 values[1] = values[0];
2734 float arr_stack[32];
2738 if (array_len > 32) {
2739 arr = MEM_mallocN(sizeof(float) * array_len, __func__);
2745 RNA_property_float_get_array(ptr, prop, arr);
2746 values[0] = values[1] = arr[0];
2747 for (i = 1; i < array_len; i++) {
2748 values[0] = MIN2(values[0], arr[i]);
2749 values[1] = MAX2(values[1], arr[i]);
2752 if (arr != arr_stack) {
2758 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2760 float tmp[RNA_MAX_ARRAY_LENGTH];
2761 int len = rna_ensure_property_array_length(ptr, prop);
2763 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2764 BLI_assert(RNA_property_array_check(prop) != false);
2765 BLI_assert(index >= 0);
2766 BLI_assert(index < len);
2768 if (len <= RNA_MAX_ARRAY_LENGTH) {
2769 RNA_property_float_get_array(ptr, prop, tmp);
2773 float *tmparray, value;
2775 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2776 RNA_property_float_get_array(ptr, prop, tmparray);
2777 value = tmparray[index];
2778 MEM_freeN(tmparray);
2784 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
2786 FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2790 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2791 BLI_assert(RNA_property_array_check(prop) != false);
2793 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2794 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2795 if (prop->arraydimension == 0) {
2796 if (idprop->type == IDP_FLOAT)
2797 IDP_Float(idprop) = values[0];
2799 IDP_Double(idprop) = values[0];
2801 else if (idprop->subtype == IDP_FLOAT) {
2802 memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2805 for (i = 0; i < idprop->len; i++)
2806 ((double *)IDP_Array(idprop))[i] = values[i];
2809 rna_idproperty_touch(idprop);
2811 else if (prop->arraydimension == 0)
2812 RNA_property_float_set(ptr, prop, values[0]);
2813 else if (fprop->setarray) {
2814 fprop->setarray(ptr, values);
2816 else if (fprop->setarray_ex) {
2817 fprop->setarray_ex(ptr, prop, values);
2819 else if (prop->flag & PROP_EDITABLE) {
2820 IDPropertyTemplate val = {0};
2823 /* TODO: RNA_property_float_clamp_array(ptr, prop, &value); */
2825 val.array.len = prop->totarraylength;
2826 val.array.type = IDP_FLOAT;
2828 group = RNA_struct_idprops(ptr, 1);
2830 idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2831 IDP_AddToGroup(group, idprop);
2832 memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2837 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
2839 float tmp[RNA_MAX_ARRAY_LENGTH];
2840 int len = rna_ensure_property_array_length(ptr, prop);
2842 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2843 BLI_assert(RNA_property_array_check(prop) != false);
2844 BLI_assert(index >= 0);
2845 BLI_assert(index < len);
2847 if (len <= RNA_MAX_ARRAY_LENGTH) {
2848 RNA_property_float_get_array(ptr, prop, tmp);
2850 RNA_property_float_set_array(ptr, prop, tmp);
2855 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2856 RNA_property_float_get_array(ptr, prop, tmparray);
2857 tmparray[index] = value;
2858 RNA_property_float_set_array(ptr, prop, tmparray);
2859 MEM_freeN(tmparray);
2863 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2865 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
2867 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2868 BLI_assert(RNA_property_array_check(prop) == false);
2870 return fprop->defaultvalue;
2873 void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, float *values)
2875 FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
2877 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2878 BLI_assert(RNA_property_array_check(prop) != false);
2880 if (prop->arraydimension == 0)
2881 values[0] = fprop->defaultvalue;
2882 else if (fprop->defaultarray)
2883 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2885 memset(values, 0, sizeof(float) * prop->totarraylength);
2888 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2890 float tmp[RNA_MAX_ARRAY_LENGTH];
2891 int len = rna_ensure_property_array_length(ptr, prop);
2893 BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2894 BLI_assert(RNA_property_array_check(prop) != false);
2895 BLI_assert(index >= 0);
2896 BLI_assert(index < prop->totarraylength);
2898 if (len <= RNA_MAX_ARRAY_LENGTH) {
2899 RNA_property_float_get_default_array(ptr, prop, tmp);
2903 float *tmparray, value;
2905 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2906 RNA_property_float_get_default_array(ptr, prop, tmparray);
2907 value = tmparray[index];
2908 MEM_freeN(tmparray);
2914 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
2916 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2919 BLI_assert(RNA_property_type(prop) == PROP_STRING);
2921 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2922 /* editing bytes is not 100% supported
2923 * since they can contain NIL chars */
2924 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2925 memcpy(value, IDP_String(idprop), idprop->len);
2926 value[idprop->len] = '\0';
2929 memcpy(value, IDP_String(idprop), idprop->len);
2932 else if (sprop->get) {
2933 sprop->get(ptr, value);
2935 else if (sprop->get_ex) {
2936 sprop->get_ex(ptr, prop, value);
2939 strcpy(value, sprop->defaultvalue);
2943 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop,
2944 char *fixedbuf, int fixedlen, int *r_len)
2949 BLI_assert(RNA_property_type(prop) == PROP_STRING);
2951 length = RNA_property_string_length(ptr, prop);
2953 if (length + 1 < fixedlen)
2956 buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
2959 /* safety check to ensure the string is actually set */
2963 RNA_property_string_get(ptr, prop, buf);
2966 BLI_assert(buf[length] == '\0');
2976 /* this is the length without \0 terminator */
2977 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
2979 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2982 BLI_assert(RNA_property_type(prop) == PROP_STRING);
2984 if ((idprop = rna_idproperty_check(&prop, ptr))) {
2985 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2990 /* these _must_ stay in sync */
2991 BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
2993 return idprop->len - 1;
2996 else if (sprop->length)
2997 return sprop->length(ptr);
2998 else if (sprop->length_ex)
2999 return sprop->length_ex(ptr, prop);
3001 return strlen(sprop->defaultvalue);
3004 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
3006 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3009 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3011 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3012 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
3013 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
3014 rna_idproperty_touch(idprop);
3016 else if (sprop->set)
3017 sprop->set(ptr, value); /* set function needs to clamp its self */
3018 else if (sprop->set_ex)
3019 sprop->set_ex(ptr, prop, value); /* set function needs to clamp its self */
3020 else if (prop->flag & PROP_EDITABLE) {
3023 group = RNA_struct_idprops(ptr, 1);
3025 IDP_AddToGroup(group, IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop)));
3029 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
3031 StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
3033 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3035 strcpy(value, sprop->defaultvalue);
3038 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
3043 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3045 length = RNA_property_string_default_length(ptr, prop);
3047 if (length + 1 < fixedlen)
3050 buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
3052 RNA_property_string_get_default(ptr, prop, buf);
3057 /* this is the length without \0 terminator */
3058 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3060 StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3062 BLI_assert(RNA_property_type(prop) == PROP_STRING);
3064 return strlen(sprop->defaultvalue);
3067 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
3069 EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3072 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3074 if ((idprop = rna_idproperty_check(&prop, ptr)))
3075 return IDP_Int(idprop);
3076 else if (eprop->get)
3077 return eprop->get(ptr);
3078 else if (eprop->get_ex)
3079 return eprop->get_ex(ptr, prop);
3081 return eprop->defaultvalue;
3084 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
3086 EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3089 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3091 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3092 IDP_Int(idprop) = value;
3093 rna_idproperty_touch(idprop);
3095 else if (eprop->set) {
3096 eprop->set(ptr, value);
3098 else if (eprop->set_ex) {
3099 eprop->set_ex(ptr, prop, value);
3101 else if (prop->flag & PROP_EDITABLE) {
3102 IDPropertyTemplate val = {0};
3107 group = RNA_struct_idprops(ptr, 1);
3109 IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
3113 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3115 EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
3117 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3119 return eprop->defaultvalue;
3122 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
3124 EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3126 BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3128 return eprop->py_data;
3132 * Get the value of the item that is \a step items away from \a from_value.
3134 * \param from_value: Item value to start stepping from.
3135 * \param step: Absolute value defines step size, sign defines direction.
3136 * E.g to get the next item, pass 1, for the previous -1.
3138 int RNA_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
3140 const EnumPropertyItem *item_array;
3143 int result_value = from_value;
3145 int single_step = (step < 0) ? -1 : 1;
3148 RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
3149 i = RNA_enum_from_value(item_array, from_value);
3153 i = mod_i(i + single_step, totitem);
3154 if (item_array[i].identifier[0]) {
3155 step_tot += single_step;
3157 } while ((i != i_init) && (step_tot != step));
3160 result_value = item_array[i].value;
3164 MEM_freeN((void *)item_array);
3167 return result_value;
3170 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
3172 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3175 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3177 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3178 pprop = (PointerPropertyRNA *)prop;
3180 if (RNA_struct_is_ID(pprop->type)) {
3181 return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop));
3184 /* for groups, data is idprop itself */
3186 return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
3188 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
3190 else if (pprop->get) {
3191 return pprop->get(ptr);
3193 else if (prop->flag & PROP_IDPROPERTY) {
3194 /* XXX temporary hack to add it automatically, reading should
3195 * never do any write ops, to ensure thread safety etc .. */
3196 RNA_property_pointer_add(ptr, prop);
3197 return RNA_property_pointer_get(ptr, prop);
3200 return PointerRNA_NULL;
3204 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
3206 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3207 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3210 if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
3211 printf("%s: expected %s type, not %s.\n", __func__, pprop->type->identifier, ptr_value.type->identifier);
3217 !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
3218 !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
3220 pprop->set(ptr, ptr_value);
3223 else if (prop->flag & PROP_EDITABLE) {
3224 IDPropertyTemplate val = {0};
3227 val.id = ptr_value.data;
3229 group = RNA_struct_idprops(ptr, true);
3231 IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier));
3236 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
3238 /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
3240 /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
3242 return PointerRNA_NULL; /* FIXME: there has to be a way... */
3245 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
3247 /*IDProperty *idprop;*/
3249 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3251 if ((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
3252 /* already exists */
3254 else if (prop->flag & PROP_IDPROPERTY) {
3255 IDPropertyTemplate val = {0};
3260 group = RNA_struct_idprops(ptr, 1);
3262 IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
3265 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
3268 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
3270 IDProperty *idprop, *group;
3272 BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3274 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3275 group = RNA_struct_idprops(ptr, 0);
3278 IDP_FreeFromGroup(group, idprop);
3282 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
3285 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
3287 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
3289 iter->ptr.data = rna_iterator_array_get(iter);
3290 iter->ptr.type = cprop->item_type;
3291 rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
3294 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
3298 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3300 memset(iter, 0, sizeof(*iter));
3302 if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
3303 iter->parent = *ptr;
3307 rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
3309 rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
3312 rna_property_collection_get_idp(iter);
3317 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3318 cprop->begin(iter, ptr);
3322 void RNA_property_collection_next(CollectionPropertyIterator *iter)
3324 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3327 rna_iterator_array_next(iter);
3330 rna_property_collection_get_idp(iter);
3336 void RNA_property_collection_skip(CollectionPropertyIterator *iter, int num)
3338 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3341 if (num > 1 && (iter->idprop || (cprop->property.flag_internal & PROP_INTERN_RAW_ARRAY))) {
3342 /* fast skip for array */
3343 ArrayIterator *internal = &iter->internal.array;
3345 if (!internal->skip) {
3346 internal->ptr += internal->itemsize * (num - 1);
3347 iter->valid = (internal->ptr < internal->endptr);
3349 RNA_property_collection_next(iter);
3354 /* slow iteration otherwise */
3355 for (i = 0; i < num && iter->valid; i++)
3356 RNA_property_collection_next(iter);
3359 void RNA_property_collection_end(CollectionPropertyIterator *iter)
3361 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3364 rna_iterator_array_end(iter);
3369 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
3371 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3374 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3376 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3379 else if (cprop->length) {
3380 return cprop->length(ptr);
3383 CollectionPropertyIterator iter;
3386 RNA_property_collection_begin(ptr, prop, &iter);
3387 for (; iter.valid; RNA_property_collection_next(&iter))
3389 RNA_property_collection_end(&iter);
3395 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
3398 /* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
3400 BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3402 if ((idprop = rna_idproperty_check(&prop, ptr))) {
3403 IDPropertyTemplate val = {0};
3406 item = IDP_New(IDP_GROUP, &val, "");
3407 IDP_AppendArray(idprop, item);
3408 /* IDP_FreeProperty(item); *//* IDP_AppendArray does a shallow copy (memcpy), only free memory */
3410 rna_idproperty_touch(idprop);
3412 else if (prop->flag & PROP_IDPROPERTY) {
3413 IDProperty *group, *item;
3414 IDPropertyTemplate val = {0};
3416 group = RNA_struct_idprops(ptr, 1);
3418 idprop = IDP_NewIDPArray(prop->identifier);
3419 IDP_AddToGroup(group, idprop);