RNA: sync API changes from 2.8
[blender.git] / source / blender / makesrna / intern / rna_access.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * Contributor(s): Blender Foundation (2008).
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/makesrna/intern/rna_access.c
24  *  \ingroup RNA
25  */
26
27
28 #include <stdlib.h>
29 #include <stddef.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_ID.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_windowmanager_types.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_dynstr.h"
42 #include "BLI_ghash.h"
43 #include "BLI_math.h"
44
45 #include "BLF_api.h"
46 #include "BLT_translation.h"
47
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_main.h"
55 #include "BKE_report.h"
56
57 #include "RNA_access.h"
58 #include "RNA_define.h"
59 #include "RNA_enum_types.h"
60
61 #include "WM_api.h"
62
63 /* flush updates */
64 #include "DNA_object_types.h"
65 #include "BKE_depsgraph.h"
66 #include "WM_types.h"
67
68 #include "rna_internal.h"
69
70 const PointerRNA PointerRNA_NULL = {{NULL}};
71
72 /* Init/Exit */
73
74 void RNA_init(void)
75 {
76         StructRNA *srna;
77         PropertyRNA *prop;
78
79         BLENDER_RNA.structs_map = BLI_ghash_str_new_ex(__func__, 2048);
80         BLENDER_RNA.structs_len = 0;
81
82         for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
83                 if (!srna->cont.prophash) {
84                         srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
85
86                         for (prop = srna->cont.properties.first; prop; prop = prop->next) {
87                                 if (!(prop->flag_internal & PROP_INTERN_BUILTIN)) {
88                                         BLI_ghash_insert(srna->cont.prophash, (void *)prop->identifier, prop);
89                                 }
90                         }
91                 }
92                 BLI_assert(srna->flag & STRUCT_PUBLIC_NAMESPACE);
93                 BLI_ghash_insert(BLENDER_RNA.structs_map, (void *)srna->identifier, srna);
94                 BLENDER_RNA.structs_len += 1;
95         }
96 }
97
98 void RNA_exit(void)
99 {
100         StructRNA *srna;
101         
102         RNA_property_update_cache_free();
103         
104         for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
105                 if (srna->cont.prophash) {
106                         BLI_ghash_free(srna->cont.prophash, NULL, NULL);
107                         srna->cont.prophash = NULL;
108                 }
109         }
110
111         RNA_free(&BLENDER_RNA);
112 }
113
114 /* Pointer */
115
116 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
117 {
118         r_ptr->id.data = NULL;
119         r_ptr->type = &RNA_BlendData;
120         r_ptr->data = main;
121 }
122
123 void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
124 {
125         StructRNA *type, *idtype = NULL;
126
127         if (id) {
128                 PointerRNA tmp = {{NULL}};
129                 tmp.data = id;
130                 idtype = rna_ID_refine(&tmp);
131                 
132                 while (idtype->refine) {
133                         type = idtype->refine(&tmp);
134
135                         if (type == idtype)
136                                 break;
137                         else
138                                 idtype = type;
139                 }
140         }
141         
142         r_ptr->id.data = id;
143         r_ptr->type = idtype;
144         r_ptr->data = id;
145 }
146
147 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
148 {
149 #if 0 /* UNUSED */
150         StructRNA *idtype = NULL;
151
152         if (id) {
153                 PointerRNA tmp = {{0}};
154                 tmp.data = id;
155                 idtype = rna_ID_refine(&tmp);
156         }
157 #endif
158
159         r_ptr->id.data = id;
160         r_ptr->type = type;
161         r_ptr->data = data;
162
163         if (data) {
164                 while (r_ptr->type && r_ptr->type->refine) {
165                         StructRNA *rtype = r_ptr->type->refine(r_ptr);
166
167                         if (rtype == r_ptr->type)
168                                 break;
169                         else
170                                 r_ptr->type = rtype;
171                 }
172         }
173 }
174
175 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
176 {
177         if (type && type->flag & STRUCT_ID) {
178                 ptr->id.data = ptr->data;
179         }
180         else {
181                 ptr->id.data = parent->id.data;
182         }
183 }
184
185 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
186 {
187         r_ptr->id.data = NULL;
188         r_ptr->type = &RNA_BlenderRNA;
189         r_ptr->data = &BLENDER_RNA;
190 }
191
192 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
193 {
194         if (data) {
195                 PointerRNA result;
196                 result.data = data;
197                 result.type = type;
198                 rna_pointer_inherit_id(type, ptr, &result);
199
200                 while (result.type->refine) {
201                         type = result.type->refine(&result);
202
203                         if (type == result.type)
204                                 break;
205                         else
206                                 result.type = type;
207                 }
208                 return result;
209         }
210         else {
211                 return PointerRNA_NULL;
212         }
213 }
214
215 /**/
216 void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
217 {
218 #if 0 /* works but this case if covered by more general code below. */
219         if (RNA_struct_is_ID(ptr->type)) {
220                 /* simple case */
221                 RNA_id_pointer_create(ptr->id.data, r_ptr);
222         }
223         else
224 #endif
225         {
226                 StructRNA *base;
227                 PointerRNA t_ptr;
228                 *r_ptr = *ptr; /* initialize as the same in case cant recast */
229
230                 for (base = ptr->type->base; base; base = base->base) {
231                         t_ptr = rna_pointer_inherit_refine(ptr, base, ptr->data);
232                         if (t_ptr.type && t_ptr.type != ptr->type) {
233                                 *r_ptr = t_ptr;
234                         }
235                 }
236         }
237 }
238
239 /* ID Properties */
240
241 static void rna_idproperty_touch(IDProperty *idprop)
242 {
243         /* so the property is seen as 'set' by rna */
244         idprop->flag &= ~IDP_FLAG_GHOST;
245 }
246
247 /* return a UI local ID prop definition for this prop */
248 static IDProperty *rna_idproperty_ui(PropertyRNA *prop)
249 {
250         IDProperty *idprop;
251
252         for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
253                 if (STREQ(RNA_IDP_UI, idprop->name))
254                         break;
255         }
256
257         if (idprop == NULL) {
258                 for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
259                         if (STREQ(RNA_IDP_UI, idprop->name))
260                                 break;
261                 }
262         }
263
264         if (idprop) {
265                 return IDP_GetPropertyTypeFromGroup(idprop, ((IDProperty *)prop)->name, IDP_GROUP);
266         }
267
268         return NULL;
269 }
270
271 IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create)
272 {
273         StructRNA *type = ptr->type;
274
275         if (type && type->idproperties)
276                 return type->idproperties(ptr, create);
277         
278         return NULL;
279 }
280
281 bool RNA_struct_idprops_check(StructRNA *srna)
282 {
283         return (srna && srna->idproperties);
284 }
285
286 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
287 {
288         IDProperty *group = RNA_struct_idprops(ptr, 0);
289
290         if (group)
291                 return IDP_GetPropertyFromGroup(group, name);
292
293         return NULL;
294 }
295
296 static void rna_idproperty_free(PointerRNA *ptr, const char *name)
297 {
298         IDProperty *group = RNA_struct_idprops(ptr, 0);
299
300         if (group) {
301                 IDProperty *idprop = IDP_GetPropertyFromGroup(group, name);
302                 if (idprop) {
303                         IDP_FreeFromGroup(group, idprop);
304                 }
305         }
306 }
307
308 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
309 {
310         if (prop->magic == RNA_MAGIC) {
311                 int arraylen[RNA_MAX_ARRAY_DIMENSION];
312                 return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) : prop->totarraylength;
313         }
314         else {
315                 IDProperty *idprop = (IDProperty *)prop;
316
317                 if (idprop->type == IDP_ARRAY)
318                         return idprop->len;
319                 else
320                         return 0;
321         }
322 }
323
324 static bool rna_ensure_property_array_check(PropertyRNA *prop)
325 {
326         if (prop->magic == RNA_MAGIC) {
327                 return (prop->getlength || prop->totarraylength);
328         }
329         else {
330                 IDProperty *idprop = (IDProperty *)prop;
331
332                 return (idprop->type == IDP_ARRAY);
333         }
334 }
335
336 static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int length[])
337 {
338         if (prop->magic == RNA_MAGIC) {
339                 if (prop->getlength)
340                         prop->getlength(ptr, length);
341                 else
342                         memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
343         }
344         else {
345                 IDProperty *idprop = (IDProperty *)prop;
346
347                 if (idprop->type == IDP_ARRAY)
348                         length[0] = idprop->len;
349                 else
350                         length[0] = 0;
351         }
352 }
353
354 static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
355 {
356         /* this verifies if the idproperty actually matches the property
357          * description and otherwise removes it. this is to ensure that
358          * rna property access is type safe, e.g. if you defined the rna
359          * to have a certain array length you can count on that staying so */
360         
361         switch (idprop->type) {
362                 case IDP_IDPARRAY:
363                         if (prop->type != PROP_COLLECTION)
364                                 return false;
365                         break;
366                 case IDP_ARRAY:
367                         if (rna_ensure_property_array_length(ptr, prop) != idprop->len)
368                                 return false;
369
370                         if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
371                                 return false;
372                         if (idprop->subtype == IDP_INT && !ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
373                                 return false;
374
375                         break;
376                 case IDP_INT:
377                         if (!ELEM(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
378                                 return false;
379                         break;
380                 case IDP_FLOAT:
381                 case IDP_DOUBLE:
382                         if (prop->type != PROP_FLOAT)
383                                 return false;
384                         break;
385                 case IDP_STRING:
386                         if (prop->type != PROP_STRING)
387                                 return false;
388                         break;
389                 case IDP_GROUP:
390                 case IDP_ID:
391                         if (prop->type != PROP_POINTER)
392                                 return false;
393                         break;
394                 default:
395                         return false;
396         }
397
398         return true;
399 }
400
401 static PropertyRNA *typemap[IDP_NUMTYPES] = {
402         (PropertyRNA *)&rna_PropertyGroupItem_string,
403         (PropertyRNA *)&rna_PropertyGroupItem_int,
404         (PropertyRNA *)&rna_PropertyGroupItem_float,
405         NULL, NULL, NULL,
406         (PropertyRNA *)&rna_PropertyGroupItem_group,
407         (PropertyRNA *)&rna_PropertyGroupItem_id,
408         (PropertyRNA *)&rna_PropertyGroupItem_double,
409         (PropertyRNA *)&rna_PropertyGroupItem_idp_array
410 };
411
412 static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
413         NULL, (PropertyRNA *)&rna_PropertyGroupItem_int_array,
414         (PropertyRNA *)&rna_PropertyGroupItem_float_array,
415         NULL, NULL, NULL,
416         (PropertyRNA *)&rna_PropertyGroupItem_collection, NULL,
417         (PropertyRNA *)&rna_PropertyGroupItem_double_array
418 };
419
420 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
421 {
422         /* This is quite a hack, but avoids some complexity in the API. we
423          * pass IDProperty structs as PropertyRNA pointers to the outside.
424          * We store some bytes in PropertyRNA structs that allows us to
425          * distinguish it from IDProperty structs. If it is an ID property,
426          * we look up an IDP PropertyRNA based on the type, and set the data
427          * pointer to the IDProperty. */
428
429         if ((*prop)->magic == RNA_MAGIC) {
430                 if ((*prop)->flag & PROP_IDPROPERTY) {
431                         IDProperty *idprop = rna_idproperty_find(ptr, (*prop)->identifier);
432
433                         if (idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) {
434                                 IDProperty *group = RNA_struct_idprops(ptr, 0);
435
436                                 IDP_FreeFromGroup(group, idprop);
437                                 return NULL;
438                         }
439
440                         return idprop;
441                 }
442                 else
443                         return NULL;
444         }
445
446         {
447                 IDProperty *idprop = (IDProperty *)(*prop);
448
449                 if (idprop->type == IDP_ARRAY)
450                         *prop = arraytypemap[(int)(idprop->subtype)];
451                 else
452                         *prop = typemap[(int)(idprop->type)];
453
454                 return idprop;
455         }
456 }
457
458 static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
459 {
460         /* the quick version if we don't need the idproperty */
461
462         if (prop->magic == RNA_MAGIC)
463                 return prop;
464
465         {
466                 IDProperty *idprop = (IDProperty *)prop;
467
468                 if (idprop->type == IDP_ARRAY)
469                         return arraytypemap[(int)(idprop->subtype)];
470                 else
471                         return typemap[(int)(idprop->type)];
472         }
473 }
474
475 static const char *rna_ensure_property_identifier(const PropertyRNA *prop)
476 {
477         if (prop->magic == RNA_MAGIC)
478                 return prop->identifier;
479         else
480                 return ((const IDProperty *)prop)->name;
481 }
482
483 static const char *rna_ensure_property_description(PropertyRNA *prop)
484 {
485         const char *description = NULL;
486
487         if (prop->magic == RNA_MAGIC)
488                 description = prop->description;
489         else {
490                 /* attempt to get the local ID values */
491                 IDProperty *idp_ui = rna_idproperty_ui(prop);
492
493                 if (idp_ui) {
494                         IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "description", IDP_STRING);
495                         if (item)
496                                 description = IDP_String(item);
497                 }
498
499                 if (description == NULL)
500                         description = ((IDProperty *)prop)->name;  /* XXX - not correct */
501         }
502
503         return description;
504 }
505
506 static const char *rna_ensure_property_name(const PropertyRNA *prop)
507 {
508         const char *name;
509
510         if (prop->magic == RNA_MAGIC)
511                 name = prop->name;
512         else
513                 name = ((const IDProperty *)prop)->name;
514
515         return name;
516 }
517
518 /* Structs */
519
520 StructRNA *RNA_struct_find(const char *identifier)
521 {
522         return BLI_ghash_lookup(BLENDER_RNA.structs_map, identifier);
523 }
524
525 const char *RNA_struct_identifier(const StructRNA *type)
526 {
527         return type->identifier;
528 }
529
530 const char *RNA_struct_ui_name(const StructRNA *type)
531 {
532         return CTX_IFACE_(type->translation_context, type->name);
533 }
534
535 const char *RNA_struct_ui_name_raw(const StructRNA *type)
536 {
537         return type->name;
538 }
539
540 int RNA_struct_ui_icon(const StructRNA *type)
541 {
542         if (type)
543                 return type->icon;
544         else
545                 return ICON_DOT;
546 }
547
548 const char *RNA_struct_ui_description(const StructRNA *type)
549 {
550         return TIP_(type->description);
551 }
552
553 const char *RNA_struct_ui_description_raw(const StructRNA *type)
554 {
555         return type->description;
556 }
557
558 const char *RNA_struct_translation_context(const StructRNA *type)
559 {
560         return type->translation_context;
561 }
562
563 PropertyRNA *RNA_struct_name_property(const StructRNA *type)
564 {
565         return type->nameproperty;
566 }
567
568 const EnumPropertyItem *RNA_struct_property_tag_defines(const StructRNA *type)
569 {
570         return type->prop_tag_defines;
571 }
572
573 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
574 {
575         return type->iteratorproperty;
576 }
577
578 StructRNA *RNA_struct_base(StructRNA *type)
579 {
580         return type->base;
581 }
582
583 /**
584  * Use to find the subtype directly below a base-type.
585  *
586  * So if type were `RNA_SpotLamp`, `RNA_struct_base_of(type, &RNA_ID)` would return `&RNA_Lamp`.
587  */
588 const StructRNA *RNA_struct_base_child_of(const StructRNA *type, const StructRNA *parent_type)
589 {
590         while (type) {
591                 if (type->base == parent_type) {
592                         return type;
593                 }
594                 type = type->base;
595         }
596         return NULL;
597 }
598
599 bool RNA_struct_is_ID(const StructRNA *type)
600 {
601         return (type->flag & STRUCT_ID) != 0;
602 }
603
604 bool RNA_struct_undo_check(const StructRNA *type)
605 {
606         return (type->flag & STRUCT_UNDO) != 0;
607 }
608
609 bool RNA_struct_idprops_register_check(const StructRNA *type)
610 {
611         return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
612 }
613
614 bool RNA_struct_idprops_datablock_allowed(const StructRNA *type)
615 {
616         return (type->flag & (STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_NO_IDPROPERTIES)) == 0;
617 }
618
619 /**
620  * Whether given type implies datablock usage by IDProperties.
621  * This is used to prevent classes allowed to have IDProperties, but not datablock ones, to indirectly use some
622  * (e.g. by assigning an IDP_GROUP containing some IDP_ID pointers...).
623  */
624 bool RNA_struct_idprops_contains_datablock(const StructRNA *type)
625 {
626         return (type->flag & (STRUCT_CONTAINS_DATABLOCK_IDPROPERTIES | STRUCT_ID)) != 0;
627 }
628
629 /* remove an id-property */
630 bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
631 {
632         IDProperty *group = RNA_struct_idprops(ptr, 0);
633
634         if (group) {
635                 IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
636                 if (idp) {
637                         IDP_FreeFromGroup(group, idp);
638
639                         return true;
640                 }
641         }
642         return false;
643 }
644
645 bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
646 {
647         const StructRNA *base;
648
649         if (srna == &RNA_AnyType)
650                 return true;
651
652         if (!type)
653                 return false;
654
655         /* ptr->type is always maximally refined */
656         for (base = type; base; base = base->base)
657                 if (base == srna)
658                         return true;
659         
660         return false;
661 }
662
663 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
664 {
665         if (identifier[0] == '[' && identifier[1] == '"') { /* "  (dummy comment to avoid confusing some
666                                                                  * function lists in text editors) */
667                 /* id prop lookup, not so common */
668                 PropertyRNA *r_prop = NULL;
669                 PointerRNA r_ptr; /* only support single level props */
670                 if (RNA_path_resolve_property(ptr, identifier, &r_ptr, &r_prop) &&
671                     (r_ptr.type == ptr->type) && (r_ptr.data == ptr->data))
672                 {
673                         return r_prop;
674                 }
675         }
676         else {
677                 /* most common case */
678                 PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
679                 PointerRNA propptr;
680
681                 if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr))
682                         return propptr.data;
683         }
684         
685         return NULL;
686 }
687
688 /* Find the property which uses the given nested struct */
689 static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
690 {
691         PropertyRNA *prop = NULL;
692
693         RNA_STRUCT_BEGIN (ptr, iprop)
694         {
695                 /* This assumes that there can only be one user of this nested struct */
696                 if (RNA_property_pointer_type(ptr, iprop) == srna) {
697                         prop = iprop;
698                         break;
699                 }
700         }
701         RNA_PROP_END;
702
703         return prop;
704 }
705
706 bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
707 {
708         /* note, prop_test could be freed memory, only use for comparison */
709
710         /* validate the RNA is ok */
711         PropertyRNA *iterprop;
712         bool found = false;
713
714         iterprop = RNA_struct_iterator_property(ptr->type);
715
716         RNA_PROP_BEGIN (ptr, itemptr, iterprop)
717         {
718                 /* PropertyRNA *prop = itemptr.data; */
719                 if (prop_test == (PropertyRNA *)itemptr.data) {
720                         found = true;
721                         break;
722                 }
723         }
724         RNA_PROP_END;
725
726         return found;
727 }
728
729 unsigned int RNA_struct_count_properties(StructRNA *srna)
730 {
731         PointerRNA struct_ptr;
732         unsigned int counter = 0;
733
734         RNA_pointer_create(NULL, srna, NULL, &struct_ptr);
735
736         RNA_STRUCT_BEGIN (&struct_ptr, prop)
737         {
738                 counter++;
739                 UNUSED_VARS(prop);
740         }
741         RNA_STRUCT_END;
742
743         return counter;
744 }
745
746 /* low level direct access to type->properties, note this ignores parent classes so should be used with care */
747 const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
748 {
749         return &srna->cont.properties;
750 }
751
752 PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
753 {
754         return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
755 }
756
757 FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
758 {
759 #if 1
760         FunctionRNA *func;
761         StructRNA *type;
762         for (type = srna; type; type = type->base) {
763                 func = (FunctionRNA *)BLI_findstring_ptr(&type->functions, identifier, offsetof(FunctionRNA, identifier));
764                 if (func) {
765                         return func;
766                 }
767         }
768         return NULL;
769
770         /* funcitonal but slow */
771 #else
772         PointerRNA tptr;
773         PropertyRNA *iterprop;
774         FunctionRNA *func;
775
776         RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr);
777         iterprop = RNA_struct_find_property(&tptr, "functions");
778
779         func = NULL;
780
781         RNA_PROP_BEGIN (&tptr, funcptr, iterprop)
782         {
783                 if (STREQ(identifier, RNA_function_identifier(funcptr.data))) {
784                         func = funcptr.data;
785                         break;
786                 }
787         }
788         RNA_PROP_END;
789
790         return func;
791 #endif
792 }
793
794 const ListBase *RNA_struct_type_functions(StructRNA *srna)
795 {
796         return &srna->functions;
797 }
798
799 StructRegisterFunc RNA_struct_register(StructRNA *type)
800 {
801         return type->reg;
802 }
803
804 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
805 {
806         do {
807                 if (type->unreg)
808                         return type->unreg;
809         } while ((type = type->base));
810
811         return NULL;
812 }
813
814 void **RNA_struct_instance(PointerRNA *ptr)
815 {
816         StructRNA *type = ptr->type;
817
818         do {
819                 if (type->instance)
820                         return type->instance(ptr);
821         } while ((type = type->base));
822
823         return NULL;
824 }
825
826 void *RNA_struct_py_type_get(StructRNA *srna)
827 {
828         return srna->py_type;
829 }
830
831 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
832 {
833         srna->py_type = py_type;
834 }
835
836 void *RNA_struct_blender_type_get(StructRNA *srna)
837 {
838         return srna->blender_type;
839 }
840
841 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
842 {
843         srna->blender_type = blender_type;
844 }
845
846 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
847 {
848         PropertyRNA *nameprop;
849
850         if (ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
851                 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
852
853         return NULL;
854 }
855
856 /**
857  * Use when registering structs with the #STRUCT_PUBLIC_NAMESPACE flag.
858  */
859 bool RNA_struct_available_or_report(ReportList *reports, const char *identifier)
860 {
861         const StructRNA *srna_exists = RNA_struct_find(identifier);
862         if (UNLIKELY(srna_exists != NULL)) {
863                 /* Use comprehensive string construction since this is such a rare occurrence
864                  * and information here may cut down time troubleshooting. */
865                 DynStr *dynstr = BLI_dynstr_new();
866                 BLI_dynstr_appendf(dynstr, "Type identifier '%s' is already in use: '", identifier);
867                 BLI_dynstr_append(dynstr, srna_exists->identifier);
868                 int i = 0;
869                 if (srna_exists->base) {
870                         for (const StructRNA *base = srna_exists->base; base; base = base->base) {
871                                 BLI_dynstr_append(dynstr, "(");
872                                 BLI_dynstr_append(dynstr, base->identifier);
873                                 i += 1;
874                         }
875                         while (i--) {
876                                 BLI_dynstr_append(dynstr, ")");
877                         }
878                 }
879                 BLI_dynstr_append(dynstr, "'.");
880                 char *result = BLI_dynstr_get_cstring(dynstr);
881                 BLI_dynstr_free(dynstr);
882                 BKE_report(reports, RPT_ERROR, result);
883                 MEM_freeN(result);
884                 return false;
885         }
886         else {
887                 return true;
888         }
889 }
890
891 bool RNA_struct_bl_idname_ok_or_report(ReportList *reports, const char *identifier, const char *sep)
892 {
893         const int len_sep = strlen(sep);
894         const int len_id = strlen(identifier);
895         const char *p = strstr(identifier, sep);
896         /* TODO: make error, for now warning until add-ons update. */
897 #if 1
898         const int report_level = RPT_WARNING;
899         const bool failure = true;
900 #else
901         const int report_level = RPT_ERROR;
902         const bool failure = false;
903 #endif
904         if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) {
905                 BKE_reportf(reports, report_level, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep);
906                 return failure;
907         }
908
909         const char *c, *start, *end, *last;
910         start = identifier;
911         end = p;
912         last = end - 1;
913         for (c = start; c != end; c++) {
914                 if (((*c >= 'A' && *c <= 'Z') ||
915                      ((c != start) && (*c >= '0' && *c <= '9')) ||
916                      ((c != start) && (c != last) && (*c == '_'))) == 0)
917                 {
918                         BKE_reportf(reports, report_level, "'%s' doesn't have upper case alpha-numeric prefix", identifier);
919                         return failure;
920                 }
921         }
922
923         start = p + len_sep;
924         end = identifier + len_id;
925         last = end - 1;
926         for (c = start; c != end; c++) {
927                 if (((*c >= 'A' && *c <= 'Z') ||
928                      (*c >= 'a' && *c <= 'z') ||
929                      (*c >= '0' && *c <= '9') ||
930                      ((c != start) && (c != last) && (*c == '_'))) == 0)
931                 {
932                         BKE_reportf(reports, report_level, "'%s' doesn't have an alpha-numeric suffix", identifier);
933                         return failure;
934                 }
935         }
936         return true;
937 }
938
939 /* Property Information */
940
941 const char *RNA_property_identifier(PropertyRNA *prop)
942 {
943         return rna_ensure_property_identifier(prop);
944 }
945
946 const char *RNA_property_description(PropertyRNA *prop)
947 {
948         return TIP_(rna_ensure_property_description(prop));
949 }
950
951 PropertyType RNA_property_type(PropertyRNA *prop)
952 {
953         return rna_ensure_property(prop)->type;
954 }
955
956 PropertySubType RNA_property_subtype(PropertyRNA *prop)
957 {
958         return rna_ensure_property(prop)->subtype;
959 }
960
961 PropertyUnit RNA_property_unit(PropertyRNA *prop)
962 {
963         return RNA_SUBTYPE_UNIT(rna_ensure_property(prop)->subtype);
964 }
965
966 int RNA_property_flag(PropertyRNA *prop)
967 {
968         return rna_ensure_property(prop)->flag;
969 }
970
971 /**
972  * Get the tags set for \a prop as int bitfield.
973  * \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this
974  *       in debug builds (to avoid performance issues in non-debug builds), which should be
975  *       the only way to set tags. Hence, at this point we assume the tag bitfield to be valid.
976  */
977 int RNA_property_tags(PropertyRNA *prop)
978 {
979         return rna_ensure_property(prop)->tags;
980 }
981
982 bool RNA_property_builtin(PropertyRNA *prop)
983 {
984         return (rna_ensure_property(prop)->flag_internal & PROP_INTERN_BUILTIN) != 0;
985 }
986
987 void *RNA_property_py_data_get(PropertyRNA *prop)
988 {
989         return prop->py_data;
990 }
991
992 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
993 {
994         return rna_ensure_property_array_length(ptr, prop);
995 }
996
997 bool RNA_property_array_check(PropertyRNA *prop)
998 {
999         return rna_ensure_property_array_check(prop);
1000 }
1001
1002 /* used by BPY to make an array from the python object */
1003 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
1004 {
1005         PropertyRNA *rprop = rna_ensure_property(prop);
1006
1007         if (length)
1008                 rna_ensure_property_multi_array_length(ptr, prop, length);
1009
1010         return rprop->arraydimension;
1011 }
1012
1013 /* Return the size of Nth dimension. */
1014 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
1015 {
1016         int len[RNA_MAX_ARRAY_DIMENSION];
1017
1018         rna_ensure_property_multi_array_length(ptr, prop, len);
1019
1020         return len[dim];
1021 }
1022
1023 char RNA_property_array_item_char(PropertyRNA *prop, int index)
1024 {
1025         const char *vectoritem = "XYZW";
1026         const char *quatitem = "WXYZ";
1027         const char *coloritem = "RGBA";
1028         PropertySubType subtype = rna_ensure_property(prop)->subtype;
1029
1030         BLI_assert(index >= 0);
1031
1032         /* get string to use for array index */
1033         if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1034                 return quatitem[index];
1035         }
1036         else if ((index < 4) && ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
1037                                      PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
1038         {
1039                 return vectoritem[index];
1040         }
1041         else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1042                 return coloritem[index];
1043         }
1044
1045         return '\0';
1046 }
1047
1048 int RNA_property_array_item_index(PropertyRNA *prop, char name)
1049 {
1050         PropertySubType subtype = rna_ensure_property(prop)->subtype;
1051
1052         /* get index based on string name/alias */
1053         /* maybe a function to find char index in string would be better than all the switches */
1054         if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1055                 switch (name) {
1056                         case 'w':
1057                                 return 0;
1058                         case 'x':
1059                                 return 1;
1060                         case 'y':
1061                                 return 2;
1062                         case 'z':
1063                                 return 3;
1064                 }
1065         }
1066         else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
1067                        PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
1068         {
1069                 switch (name) {
1070                         case 'x':
1071                                 return 0;
1072                         case 'y':
1073                                 return 1;
1074                         case 'z':
1075                                 return 2;
1076                         case 'w':
1077                                 return 3;
1078                 }
1079         }
1080         else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1081                 switch (name) {
1082                         case 'r':
1083                                 return 0;
1084                         case 'g':
1085                                 return 1;
1086                         case 'b':
1087                                 return 2;
1088                         case 'a':
1089                                 return 3;
1090                 }
1091         }
1092
1093         return -1;
1094 }
1095
1096
1097 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
1098 {
1099         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1100         int softmin, softmax;
1101
1102         if (prop->magic != RNA_MAGIC) {
1103                 /* attempt to get the local ID values */
1104                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1105
1106                 if (idp_ui) {
1107                         IDProperty *item;
1108
1109                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
1110                         *hardmin = item ? IDP_Int(item) : INT_MIN;
1111
1112                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
1113                         *hardmax = item ? IDP_Int(item) : INT_MAX;
1114
1115                         return;
1116                 }
1117         }
1118
1119         if (iprop->range) {
1120                 *hardmin = INT_MIN;
1121                 *hardmax = INT_MAX;
1122
1123                 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1124         }
1125         else if (iprop->range_ex) {
1126                 *hardmin = INT_MIN;
1127                 *hardmax = INT_MAX;
1128
1129                 iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1130         }
1131         else {
1132                 *hardmin = iprop->hardmin;
1133                 *hardmax = iprop->hardmax;
1134         }
1135 }
1136
1137 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
1138 {
1139         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1140         int hardmin, hardmax;
1141         
1142         if (prop->magic != RNA_MAGIC) {
1143                 /* attempt to get the local ID values */
1144                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1145
1146                 if (idp_ui) {
1147                         IDProperty *item;
1148
1149                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
1150                         *softmin = item ? IDP_Int(item) : INT_MIN;
1151
1152                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
1153                         *softmax = item ? IDP_Int(item) : INT_MAX;
1154
1155                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
1156                         *step = item ? IDP_Int(item) : 1;
1157
1158                         return;
1159                 }
1160         }
1161
1162         *softmin = iprop->softmin;
1163         *softmax = iprop->softmax;
1164
1165         if (iprop->range) {
1166                 hardmin = INT_MIN;
1167                 hardmax = INT_MAX;
1168
1169                 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1170
1171                 *softmin = max_ii(*softmin, hardmin);
1172                 *softmax = min_ii(*softmax, hardmax);
1173         }
1174         else if (iprop->range_ex) {
1175                 hardmin = INT_MIN;
1176                 hardmax = INT_MAX;
1177
1178                 iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1179
1180                 *softmin = max_ii(*softmin, hardmin);
1181                 *softmax = min_ii(*softmax, hardmax);
1182         }
1183
1184         *step = iprop->step;
1185 }
1186
1187 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1188 {
1189         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1190         float softmin, softmax;
1191
1192         if (prop->magic != RNA_MAGIC) {
1193                 /* attempt to get the local ID values */
1194                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1195
1196                 if (idp_ui) {
1197                         IDProperty *item;
1198
1199                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
1200                         *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1201
1202                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1203                         *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1204
1205                         return;
1206                 }
1207         }
1208
1209         if (fprop->range) {
1210                 *hardmin = -FLT_MAX;
1211                 *hardmax = FLT_MAX;
1212
1213                 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1214         }
1215         else if (fprop->range_ex) {
1216                 *hardmin = -FLT_MAX;
1217                 *hardmax = FLT_MAX;
1218
1219                 fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1220         }
1221         else {
1222                 *hardmin = fprop->hardmin;
1223                 *hardmax = fprop->hardmax;
1224         }
1225 }
1226
1227 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax,
1228                                  float *step, float *precision)
1229 {
1230         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1231         float hardmin, hardmax;
1232
1233         if (prop->magic != RNA_MAGIC) {
1234                 /* attempt to get the local ID values */
1235                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1236
1237                 if (idp_ui) {
1238                         IDProperty *item;
1239
1240                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1241                         *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1242
1243                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1244                         *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1245
1246                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1247                         *step = item ? (float)IDP_Double(item) : 1.0f;
1248
1249                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1250                         *precision = item ? (float)IDP_Double(item) : 3.0f;
1251
1252                         return;
1253                 }
1254         }
1255
1256         *softmin = fprop->softmin;
1257         *softmax = fprop->softmax;
1258
1259         if (fprop->range) {
1260                 hardmin = -FLT_MAX;
1261                 hardmax = FLT_MAX;
1262
1263                 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1264
1265                 *softmin = max_ff(*softmin, hardmin);
1266                 *softmax = min_ff(*softmax, hardmax);
1267         }
1268         else if (fprop->range_ex) {
1269                 hardmin = -FLT_MAX;
1270                 hardmax = FLT_MAX;
1271
1272                 fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1273
1274                 *softmin = max_ff(*softmin, hardmin);
1275                 *softmax = min_ff(*softmax, hardmax);
1276         }
1277
1278         *step = fprop->step;
1279         *precision = (float)fprop->precision;
1280 }
1281
1282 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1283 {
1284         float min, max;
1285
1286         RNA_property_float_range(ptr, prop, &min, &max);
1287
1288         if (*value < min) {
1289                 *value = min;
1290                 return -1;
1291         }
1292         else if (*value > max) {
1293                 *value = max;
1294                 return 1;
1295         }
1296         else {
1297                 return 0;
1298         }
1299 }
1300
1301 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1302 {
1303         int min, max;
1304
1305         RNA_property_int_range(ptr, prop, &min, &max);
1306
1307         if (*value < min) {
1308                 *value = min;
1309                 return -1;
1310         }
1311         else if (*value > max) {
1312                 *value = max;
1313                 return 1;
1314         }
1315         else {
1316                 return 0;
1317         }
1318 }
1319
1320 /* this is the max length including \0 terminator.
1321  * '0' used when their is no maximum */
1322 int RNA_property_string_maxlength(PropertyRNA *prop)
1323 {
1324         StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1325         return sprop->maxlength;
1326 }
1327
1328 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1329 {
1330         prop = rna_ensure_property(prop);
1331
1332         if (prop->type == PROP_POINTER) {
1333                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1334
1335                 if (pprop->typef)
1336                         return pprop->typef(ptr);
1337                 else if (pprop->type)
1338                         return pprop->type;
1339         }
1340         else if (prop->type == PROP_COLLECTION) {
1341                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1342
1343                 if (cprop->item_type)
1344                         return cprop->item_type;
1345         }
1346         /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1347
1348         return &RNA_UnknownType;
1349 }
1350
1351 int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1352 {
1353         prop = rna_ensure_property(prop);
1354
1355         if (prop->type == PROP_POINTER) {
1356                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1357
1358                 if (pprop->poll) {
1359                         if (rna_idproperty_check(&prop, ptr)) {
1360                                 return ((PropPointerPollFuncPy) pprop->poll)(ptr, *value, prop);
1361                         }
1362                         else {
1363                                 return pprop->poll(ptr, *value);
1364                         }
1365                 }
1366
1367                 return 1;
1368         }
1369
1370         printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
1371         return 0;
1372 }
1373
1374 /* Reuse for dynamic types  */
1375 const EnumPropertyItem DummyRNA_NULL_items[] = {
1376         {0, NULL, 0, NULL, NULL}
1377 };
1378
1379 /* Reuse for dynamic types with default value */
1380 const EnumPropertyItem DummyRNA_DEFAULT_items[] = {
1381         {0, "DEFAULT", 0, "Default", ""},
1382         {0, NULL, 0, NULL, NULL}
1383 };
1384
1385 void RNA_property_enum_items_ex(
1386         bContext *C, PointerRNA *ptr, PropertyRNA *prop, const bool use_static,
1387         const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1388 {
1389         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1390
1391         *r_free = false;
1392
1393         if (!use_static && eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1394                 const EnumPropertyItem *item;
1395
1396                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1397                         item = eprop->itemf(NULL, ptr, prop, r_free);
1398                 else
1399                         item = eprop->itemf(C, ptr, prop, r_free);
1400
1401                 /* any callbacks returning NULL should be fixed */
1402                 BLI_assert(item != NULL);
1403
1404                 if (r_totitem) {
1405                         int tot;
1406                         for (tot = 0; item[tot].identifier; tot++) {
1407                                 /* pass */
1408                         }
1409                         *r_totitem = tot;
1410                 }
1411
1412                 *r_item = item;
1413         }
1414         else {
1415                 *r_item = eprop->item;
1416                 if (r_totitem)
1417                         *r_totitem = eprop->totitem;
1418         }
1419 }
1420
1421 void RNA_property_enum_items(
1422         bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1423         const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1424 {
1425         RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free);
1426 }
1427
1428 #ifdef WITH_INTERNATIONAL
1429 static void property_enum_translate(
1430         PropertyRNA *prop, EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1431 {
1432         if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1433                 int i;
1434
1435                 /* Note: Only do those tests once, and then use BLT_pgettext. */
1436                 bool do_iface = BLT_translate_iface();
1437                 bool do_tooltip = BLT_translate_tooltips();
1438                 EnumPropertyItem *nitem;
1439
1440                 if (!(do_iface || do_tooltip))
1441                         return;
1442
1443                 if (*r_free) {
1444                         nitem = *r_item;
1445                 }
1446                 else {
1447                         const EnumPropertyItem *item = *r_item;
1448                         int tot;
1449
1450                         if (r_totitem) {
1451                                 tot = *r_totitem;
1452                         }
1453                         else {
1454                                 /* count */
1455                                 for (tot = 0; item[tot].identifier; tot++) {
1456                                         /* pass */
1457                                 }
1458                         }
1459
1460                         nitem = MEM_mallocN(sizeof(EnumPropertyItem) * (tot + 1), "enum_items_gettexted");
1461                         memcpy(nitem, item, sizeof(EnumPropertyItem) * (tot + 1));
1462
1463                         *r_free = true;
1464                 }
1465
1466                 for (i = 0; nitem[i].identifier; i++) {
1467                         if (nitem[i].name && do_iface) {
1468                                 nitem[i].name = BLT_pgettext(prop->translation_context, nitem[i].name);
1469                         }
1470                         if (nitem[i].description && do_tooltip) {
1471                                 nitem[i].description = BLT_pgettext(NULL, nitem[i].description);
1472                         }
1473                 }
1474
1475                 *r_item = nitem;
1476         }
1477 }
1478 #endif
1479
1480 void RNA_property_enum_items_gettexted(
1481         bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1482         const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1483 {
1484         RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
1485
1486 #ifdef WITH_INTERNATIONAL
1487         /* Normally dropping 'const' is _not_ ok, in this case it's only modified if we own the memory
1488          * so allow the exception (callers are creating new arrays in this case). */
1489         property_enum_translate(prop, (EnumPropertyItem **)r_item, r_totitem, r_free);
1490 #endif
1491 }
1492
1493 void RNA_property_enum_items_gettexted_all(
1494         bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1495         const EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1496 {
1497         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1498         int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
1499         /* first return all items */
1500         EnumPropertyItem *item_array = MEM_mallocN(mem_size, "enum_gettext_all");
1501         *r_free = true;
1502         memcpy(item_array, eprop->item, mem_size);
1503
1504         if (r_totitem) {
1505                 *r_totitem = eprop->totitem;
1506         }
1507
1508         if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1509                 const EnumPropertyItem *item;
1510                 int i;
1511                 bool free = false;
1512
1513                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1514                         item = eprop->itemf(NULL, ptr, prop, &free);
1515                 else
1516                         item = eprop->itemf(C, ptr, prop, &free);
1517
1518                 /* any callbacks returning NULL should be fixed */
1519                 BLI_assert(item != NULL);
1520
1521                 for (i = 0; i < eprop->totitem; i++) {
1522                         bool exists = false;
1523                         int i_fixed;
1524
1525                         /* items that do not exist on list are returned, but have their names/identifiers NULLed out */
1526                         for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
1527                                 if (STREQ(item[i_fixed].identifier, item_array[i].identifier)) {
1528                                         exists = true;
1529                                         break;
1530                                 }
1531                         }
1532
1533                         if (!exists) {
1534                                 item_array[i].name = NULL;
1535                                 item_array[i].identifier = "";
1536                         }
1537                 }
1538
1539                 if (free) {
1540                         MEM_freeN((void *)item);
1541                 }
1542         }
1543
1544 #ifdef WITH_INTERNATIONAL
1545         property_enum_translate(prop, &item_array, r_totitem, r_free);
1546 #endif
1547         *r_item = item_array;
1548 }
1549
1550 bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
1551 {
1552         const EnumPropertyItem *item;
1553         bool free;
1554         bool found;
1555
1556         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1557
1558         if (item) {
1559                 const int i = RNA_enum_from_identifier(item, identifier);
1560                 if (i != -1) {
1561                         *r_value = item[i].value;
1562                         found = true;
1563                 }
1564                 else {
1565                         found = false;
1566                 }
1567
1568                 if (free) {
1569                         MEM_freeN((void *)item);
1570                 }
1571         }
1572         else {
1573                 found = false;
1574         }
1575         return found;
1576 }
1577
1578 bool RNA_enum_identifier(const EnumPropertyItem *item, const int value, const char **r_identifier)
1579 {
1580         const int i = RNA_enum_from_value(item, value);
1581         if (i != -1) {
1582                 *r_identifier = item[i].identifier;
1583                 return true;
1584         }
1585         else {
1586                 return false;
1587         }
1588 }
1589
1590 int RNA_enum_bitflag_identifiers(const EnumPropertyItem *item, const int value, const char **r_identifier)
1591 {
1592         int index = 0;
1593         for (; item->identifier; item++) {
1594                 if (item->identifier[0] && item->value & value) {
1595                         r_identifier[index++] = item->identifier;
1596                 }
1597         }
1598         r_identifier[index] = NULL;
1599         return index;
1600 }
1601
1602 bool RNA_enum_name(const EnumPropertyItem *item, const int value, const char **r_name)
1603 {
1604         const int i = RNA_enum_from_value(item, value);
1605         if (i != -1) {
1606                 *r_name = item[i].name;
1607                 return true;
1608         }
1609         else {
1610                 return false;
1611         }
1612 }
1613
1614 bool RNA_enum_description(const EnumPropertyItem *item, const int value, const char **r_description)
1615 {
1616         const int i = RNA_enum_from_value(item, value);
1617         if (i != -1) {
1618                 *r_description = item[i].description;
1619                 return true;
1620         }
1621         else {
1622                 return false;
1623         }
1624 }
1625
1626 int RNA_enum_from_identifier(const EnumPropertyItem *item, const char *identifier)
1627 {
1628         int i = 0;
1629         for (; item->identifier; item++, i++) {
1630                 if (item->identifier[0] && STREQ(item->identifier, identifier)) {
1631                         return i;
1632                 }
1633         }
1634         return -1;
1635 }
1636
1637 int RNA_enum_from_value(const EnumPropertyItem *item, const int value)
1638 {
1639         int i = 0;
1640         for (; item->identifier; item++, i++) {
1641                 if (item->identifier[0] && item->value == value) {
1642                         return i;
1643                 }
1644         }
1645         return -1;
1646 }
1647
1648 unsigned int RNA_enum_items_count(const EnumPropertyItem *item)
1649 {
1650         unsigned int i = 0;
1651
1652         while (item->identifier) {
1653                 item++;
1654                 i++;
1655         }
1656
1657         return i;
1658 }
1659
1660 bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1661                                   const char **identifier)
1662 {
1663         const EnumPropertyItem *item = NULL;
1664         bool free;
1665         
1666         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1667         if (item) {
1668                 bool result;
1669                 result = RNA_enum_identifier(item, value, identifier);
1670                 if (free) {
1671                         MEM_freeN((void *)item);
1672                 }
1673                 return result;
1674         }
1675         return false;
1676 }
1677
1678 bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1679 {
1680         const EnumPropertyItem *item = NULL;
1681         bool free;
1682         
1683         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1684         if (item) {
1685                 bool result;
1686                 result = RNA_enum_name(item, value, name);
1687                 if (free) {
1688                         MEM_freeN((void *)item);
1689                 }
1690                 
1691                 return result;
1692         }
1693         return false;
1694 }
1695
1696 bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1697 {
1698         bool result;
1699
1700         result = RNA_property_enum_name(C, ptr, prop, value, name);
1701
1702         if (result) {
1703                 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1704                         if (BLT_translate_iface()) {
1705                                 *name = BLT_pgettext(prop->translation_context, *name);
1706                         }
1707                 }
1708         }
1709
1710         return result;
1711 }
1712
1713 bool RNA_property_enum_item_from_value(
1714         bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1715         EnumPropertyItem *r_item)
1716 {
1717         const EnumPropertyItem *item = NULL;
1718         bool free;
1719
1720         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1721         if (item) {
1722                 const int i = RNA_enum_from_value(item, value);
1723                 bool result;
1724
1725                 if (i != -1) {
1726                         *r_item = item[i];
1727                         result = true;
1728                 }
1729                 else {
1730                         result = false;
1731                 }
1732
1733                 if (free) {
1734                         MEM_freeN((void *)item);
1735                 }
1736
1737                 return result;
1738         }
1739         return false;
1740 }
1741
1742 bool RNA_property_enum_item_from_value_gettexted(
1743         bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1744         EnumPropertyItem *r_item)
1745 {
1746         bool result;
1747
1748         result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
1749
1750         if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1751                 if (BLT_translate_iface()) {
1752                         r_item->name = BLT_pgettext(prop->translation_context, r_item->name);
1753                 }
1754         }
1755
1756         return result;
1757 }
1758
1759 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1760                                           const char **identifier)
1761 {
1762         const EnumPropertyItem *item = NULL;
1763         bool free;
1764
1765         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1766         if (item) {
1767                 int result;
1768                 result = RNA_enum_bitflag_identifiers(item, value, identifier);
1769                 if (free)
1770                         MEM_freeN((void *)item);
1771
1772                 return result;
1773         }
1774         return 0;
1775 }
1776
1777 const char *RNA_property_ui_name(PropertyRNA *prop)
1778 {
1779         return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
1780 }
1781
1782 const char *RNA_property_ui_name_raw(PropertyRNA *prop)
1783 {
1784         return rna_ensure_property_name(prop);
1785 }
1786
1787 const char *RNA_property_ui_description(PropertyRNA *prop)
1788 {
1789         return TIP_(rna_ensure_property_description(prop));
1790 }
1791
1792 const char *RNA_property_ui_description_raw(PropertyRNA *prop)
1793 {
1794         return rna_ensure_property_description(prop);
1795 }
1796
1797 const char *RNA_property_translation_context(PropertyRNA *_prop)
1798 {
1799         PropertyRNA *prop = rna_ensure_property(_prop);
1800         return prop->translation_context;
1801 }
1802
1803 int RNA_property_ui_icon(PropertyRNA *prop)
1804 {
1805         return rna_ensure_property(prop)->icon;
1806 }
1807
1808 bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1809 {
1810         ID *id = ptr->id.data;
1811         int flag;
1812         const char *dummy_info;
1813
1814         prop = rna_ensure_property(prop);
1815         flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
1816
1817         return ((flag & PROP_EDITABLE) &&
1818                 (flag & PROP_REGISTER) == 0 &&
1819                 (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION)));
1820 }
1821
1822 /**
1823  * Version of #RNA_property_editable that tries to return additional info in \a r_info that can be exposed in UI.
1824  */
1825 bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
1826 {
1827         ID *id = ptr->id.data;
1828         int flag;
1829
1830         prop = rna_ensure_property(prop);
1831         *r_info = "";
1832
1833         /* get flag */
1834         if (prop->editable) {
1835                 flag = prop->editable(ptr, r_info);
1836         }
1837         else {
1838                 flag = prop->flag;
1839                 if ((flag & PROP_EDITABLE) == 0 || (flag & PROP_REGISTER)) {
1840                         *r_info = "This property is for internal use only and can't be edited.";
1841                 }
1842         }
1843
1844         /* property from linked data-block */
1845         if (id && ID_IS_LINKED(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
1846                 if (!(*r_info)[0]) {
1847                         *r_info = "Can't edit this property from a linked data-block.";
1848                 }
1849                 return false;
1850         }
1851
1852         return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
1853 }
1854
1855 bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
1856 {
1857         int flag;
1858         const char *dummy_info;
1859
1860         prop = rna_ensure_property(prop);
1861         flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
1862         return (flag & PROP_EDITABLE) != 0;
1863 }
1864
1865 /* same as RNA_property_editable(), except this checks individual items in an array */
1866 bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1867 {
1868         ID *id;
1869         int flag;
1870
1871         BLI_assert(index >= 0);
1872
1873         prop = rna_ensure_property(prop);
1874
1875         flag = prop->flag;
1876
1877         if (prop->editable) {
1878                 const char *dummy_info;
1879                 flag &= prop->editable(ptr, &dummy_info);
1880         }
1881
1882         if (prop->itemeditable)
1883                 flag &= prop->itemeditable(ptr, index);
1884
1885         id = ptr->id.data;
1886
1887         return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION));
1888 }
1889
1890 bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1891 {
1892         /* check that base ID-block can support animation data */
1893         if (!id_can_have_animdata(ptr->id.data))
1894                 return false;
1895         
1896         prop = rna_ensure_property(prop);
1897
1898         if (!(prop->flag & PROP_ANIMATABLE))
1899                 return false;
1900
1901         return (prop->flag & PROP_EDITABLE) != 0;
1902 }
1903
1904 bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
1905 {
1906         int len = 1, index;
1907         bool driven, special;
1908
1909         if (!prop)
1910                 return false;
1911
1912         if (RNA_property_array_check(prop))
1913                 len = RNA_property_array_length(ptr, prop);
1914
1915         for (index = 0; index < len; index++) {
1916                 if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special))
1917                         return true;
1918         }
1919
1920         return false;
1921 }
1922
1923 /* this function is to check if its possible to create a valid path from the ID
1924  * its slow so don't call in a loop */
1925 bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
1926 {
1927         char *path = RNA_path_from_ID_to_property(ptr, prop);
1928         bool ret = false;
1929
1930         if (path) {
1931                 PointerRNA id_ptr;
1932                 PointerRNA r_ptr;
1933                 PropertyRNA *r_prop;
1934
1935                 RNA_id_pointer_create(ptr->id.data, &id_ptr);
1936                 if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
1937                         ret = (prop == r_prop);
1938                 }
1939                 MEM_freeN(path);
1940         }
1941
1942         return ret;
1943 }
1944
1945
1946 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1947 {
1948         const bool is_rna = (prop->magic == RNA_MAGIC);
1949         prop = rna_ensure_property(prop);
1950
1951         if (is_rna) {
1952                 if (prop->update) {
1953                         /* ideally no context would be needed for update, but there's some
1954                          * parts of the code that need it still, so we have this exception */
1955                         if (prop->flag & PROP_CONTEXT_UPDATE) {
1956                                 if (C) {
1957                                         if (prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) {
1958                                                 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
1959                                         }
1960                                         else {
1961                                                 ((ContextUpdateFunc)prop->update)(C, ptr);
1962                                         }
1963                                 }
1964                         }
1965                         else
1966                                 prop->update(bmain, scene, ptr);
1967                 }
1968                 if (prop->noteflag)
1969                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1970         }
1971         
1972         if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
1973                 /* WARNING! This is so property drivers update the display!
1974                  * not especially nice  */
1975                 DAG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
1976                 WM_main_add_notifier(NC_WINDOW, NULL);
1977                 /* Not nice as well, but the only way to make sure material preview
1978                  * is updated with custom nodes.
1979                  */
1980                 if ((prop->flag & PROP_IDPROPERTY) != 0 &&
1981                     (ptr->id.data != NULL) &&
1982                     (GS(((ID *)ptr->id.data)->name) == ID_NT))
1983                 {
1984                         WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
1985                 }
1986         }
1987 }
1988
1989 /* must keep in sync with 'rna_property_update'
1990  * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
1991  * but this isn't likely to be a performance problem. */
1992 bool RNA_property_update_check(PropertyRNA *prop)
1993 {
1994         return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
1995 }
1996
1997 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1998 {
1999         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
2000 }
2001
2002 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
2003 {
2004         rna_property_update(NULL, bmain, scene, ptr, prop);
2005 }
2006
2007
2008 /* RNA Updates Cache ------------------------ */
2009 /* Overview of RNA Update cache system:
2010  *
2011  * RNA Update calls need to be cached in order to maintain reasonable performance
2012  * of the animation system (i.e. maintaining a somewhat interactive framerate)
2013  * while still allowing updates to be called (necessary in particular for modifier
2014  * property updates to actually work).
2015  *
2016  * The cache is structured with a dual-layer structure
2017  * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
2018  *        and most updates end up using just that anyways)
2019  * - L2 = Update functions to be called on those PointerRNA's
2020  */
2021
2022 /* cache element */
2023 typedef struct tRnaUpdateCacheElem {
2024         struct tRnaUpdateCacheElem *next, *prev;
2025         
2026         PointerRNA ptr;     /* L1 key - id as primary, data secondary/ignored? */
2027         ListBase L2Funcs;   /* L2 functions (LinkData<RnaUpdateFuncRef>) */
2028 } tRnaUpdateCacheElem;
2029
2030 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
2031 static ListBase rna_updates_cache = {NULL, NULL};
2032
2033 /* ........................... */
2034
2035 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
2036 {
2037         const bool is_rna = (prop->magic == RNA_MAGIC);
2038         tRnaUpdateCacheElem *uce = NULL;
2039         UpdateFunc fn = NULL;
2040         LinkData *ld;
2041         
2042         /* sanity check */
2043         if (NULL == ptr)
2044                 return;
2045                 
2046         prop = rna_ensure_property(prop);
2047         
2048         /* we can only handle update calls with no context args for now (makes animsys updates easier) */
2049         if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
2050                 return;
2051         fn = prop->update;
2052                 
2053         /* find cache element for which key matches... */
2054         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2055                 /* just match by id only for now, since most update calls that we'll encounter only really care about this */
2056                 /* TODO: later, the cache might need to have some nesting on L1 to cope better
2057                  * with these problems + some tagging to indicate we need this */
2058                 if (uce->ptr.id.data == ptr->id.data)
2059                         break;
2060         }
2061         if (uce == NULL) {
2062                 /* create new instance */
2063                 uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
2064                 BLI_addtail(&rna_updates_cache, uce);
2065                 
2066                 /* copy pointer */
2067                 RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
2068         }
2069         
2070         /* check on the update func */
2071         for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2072                 /* stop on match - function already cached */
2073                 if (fn == ld->data)
2074                         return;
2075         }
2076         /* else... if still here, we need to add it */
2077         BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
2078 }
2079
2080 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
2081 {
2082         tRnaUpdateCacheElem *uce;
2083         
2084         /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
2085         
2086         /* execute the cached updates */
2087         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2088                 LinkData *ld;
2089                 
2090                 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2091                         UpdateFunc fn = (UpdateFunc)ld->data;
2092                         fn(bmain, scene, &uce->ptr);
2093                 }
2094         }
2095 }
2096
2097 void RNA_property_update_cache_free(void)
2098 {
2099         tRnaUpdateCacheElem *uce, *ucn;
2100         
2101         for (uce = rna_updates_cache.first; uce; uce = ucn) {
2102                 ucn = uce->next;
2103                 
2104                 /* free L2 cache */
2105                 BLI_freelistN(&uce->L2Funcs);
2106                 
2107                 /* remove self */
2108                 BLI_freelinkN(&rna_updates_cache, uce);
2109         }
2110 }
2111
2112 /* ---------------------------------------------------------------------- */
2113
2114 /* Property Data */
2115
2116 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
2117 {
2118         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2119         IDProperty *idprop;
2120         int value;
2121
2122         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2123         BLI_assert(RNA_property_array_check(prop) == false);
2124
2125         if ((idprop = rna_idproperty_check(&prop, ptr)))
2126                 value = IDP_Int(idprop);
2127         else if (bprop->get)
2128                 value = bprop->get(ptr);
2129         else if (bprop->get_ex)
2130                 value = bprop->get_ex(ptr, prop);
2131         else
2132                 value = bprop->defaultvalue;
2133
2134         BLI_assert(ELEM(value, false, true));
2135
2136         return value;
2137 }
2138
2139 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2140 {
2141         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2142         IDProperty *idprop;
2143
2144         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2145         BLI_assert(RNA_property_array_check(prop) == false);
2146         BLI_assert(ELEM(value, false, true));
2147
2148         /* just in case other values are passed */
2149         if (value) value = 1;
2150
2151         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2152                 IDP_Int(idprop) = value;
2153                 rna_idproperty_touch(idprop);
2154         }
2155         else if (bprop->set) {
2156                 bprop->set(ptr, value);
2157         }
2158         else if (bprop->set_ex) {
2159                 bprop->set_ex(ptr, prop, value);
2160         }
2161         else if (prop->flag & PROP_EDITABLE) {
2162                 IDPropertyTemplate val = {0};
2163                 IDProperty *group;
2164
2165                 val.i = value;
2166
2167                 group = RNA_struct_idprops(ptr, 1);
2168                 if (group)
2169                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2170         }
2171 }
2172
2173 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2174 {
2175         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2176         IDProperty *idprop;
2177
2178         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2179         BLI_assert(RNA_property_array_check(prop) != false);
2180
2181         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2182                 if (prop->arraydimension == 0)
2183                         values[0] = RNA_property_boolean_get(ptr, prop);
2184                 else
2185                         memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2186         }
2187         else if (prop->arraydimension == 0)
2188                 values[0] = RNA_property_boolean_get(ptr, prop);
2189         else if (bprop->getarray)
2190                 bprop->getarray(ptr, values);
2191         else if (bprop->getarray_ex)
2192                 bprop->getarray_ex(ptr, prop, values);
2193         else if (bprop->defaultarray)
2194                 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
2195         else
2196                 memset(values, 0, sizeof(int) * prop->totarraylength);
2197 }
2198
2199 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2200 {
2201         int tmp[RNA_MAX_ARRAY_LENGTH];
2202         int len = rna_ensure_property_array_length(ptr, prop);
2203         int value;
2204
2205         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2206         BLI_assert(RNA_property_array_check(prop) != false);
2207         BLI_assert(index >= 0);
2208         BLI_assert(index < len);
2209
2210         if (len <= RNA_MAX_ARRAY_LENGTH) {
2211                 RNA_property_boolean_get_array(ptr, prop, tmp);
2212                 value = tmp[index];
2213         }
2214         else {
2215                 int *tmparray;
2216
2217                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2218                 RNA_property_boolean_get_array(ptr, prop, tmparray);
2219                 value = tmparray[index];
2220                 MEM_freeN(tmparray);
2221         }
2222
2223         BLI_assert(ELEM(value, false, true));
2224
2225         return value;
2226 }
2227
2228 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2229 {
2230         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2231         IDProperty *idprop;
2232
2233         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2234         BLI_assert(RNA_property_array_check(prop) != false);
2235
2236         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2237                 if (prop->arraydimension == 0)
2238                         IDP_Int(idprop) = values[0];
2239                 else
2240                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2241
2242                 rna_idproperty_touch(idprop);
2243         }
2244         else if (prop->arraydimension == 0)
2245                 RNA_property_boolean_set(ptr, prop, values[0]);
2246         else if (bprop->setarray)
2247                 bprop->setarray(ptr, values);
2248         else if (bprop->setarray_ex)
2249                 bprop->setarray_ex(ptr, prop, values);
2250         else if (prop->flag & PROP_EDITABLE) {
2251                 IDPropertyTemplate val = {0};
2252                 IDProperty *group;
2253
2254                 val.array.len = prop->totarraylength;
2255                 val.array.type = IDP_INT;
2256
2257                 group = RNA_struct_idprops(ptr, 1);
2258                 if (group) {
2259                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2260                         IDP_AddToGroup(group, idprop);
2261                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2262                 }
2263         }
2264 }
2265
2266 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2267 {
2268         int tmp[RNA_MAX_ARRAY_LENGTH];
2269         int len = rna_ensure_property_array_length(ptr, prop);
2270
2271         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2272         BLI_assert(RNA_property_array_check(prop) != false);
2273         BLI_assert(index >= 0);
2274         BLI_assert(index < len);
2275         BLI_assert(ELEM(value, false, true));
2276
2277         if (len <= RNA_MAX_ARRAY_LENGTH) {
2278                 RNA_property_boolean_get_array(ptr, prop, tmp);
2279                 tmp[index] = value;
2280                 RNA_property_boolean_set_array(ptr, prop, tmp);
2281         }
2282         else {
2283                 int *tmparray;
2284
2285                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2286                 RNA_property_boolean_get_array(ptr, prop, tmparray);
2287                 tmparray[index] = value;
2288                 RNA_property_boolean_set_array(ptr, prop, tmparray);
2289                 MEM_freeN(tmparray);
2290         }
2291 }
2292
2293 int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2294 {
2295         BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2296
2297         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2298         BLI_assert(RNA_property_array_check(prop) == false);
2299         BLI_assert(ELEM(bprop->defaultvalue, false, true));
2300
2301         return bprop->defaultvalue;
2302 }
2303
2304 void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2305 {
2306         BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2307         
2308         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2309         BLI_assert(RNA_property_array_check(prop) != false);
2310
2311         if (prop->arraydimension == 0)
2312                 values[0] = bprop->defaultvalue;
2313         else if (bprop->defaultarray)
2314                 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
2315         else
2316                 memset(values, 0, sizeof(int) * prop->totarraylength);
2317 }
2318
2319 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2320 {
2321         int tmp[RNA_MAX_ARRAY_LENGTH];
2322         int len = rna_ensure_property_array_length(ptr, prop);
2323
2324         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2325         BLI_assert(RNA_property_array_check(prop) != false);
2326         BLI_assert(index >= 0);
2327         BLI_assert(index < prop->totarraylength);
2328
2329         if (len <= RNA_MAX_ARRAY_LENGTH) {
2330                 RNA_property_boolean_get_default_array(ptr, prop, tmp);
2331                 return tmp[index];
2332         }
2333         else {
2334                 int *tmparray, value;
2335
2336                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2337                 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
2338                 value = tmparray[index];
2339                 MEM_freeN(tmparray);
2340
2341                 return value;
2342         }
2343 }
2344
2345 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
2346 {
2347         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2348         IDProperty *idprop;
2349
2350         BLI_assert(RNA_property_type(prop) == PROP_INT);
2351         BLI_assert(RNA_property_array_check(prop) == false);
2352
2353         if ((idprop = rna_idproperty_check(&prop, ptr)))
2354                 return IDP_Int(idprop);
2355         else if (iprop->get)
2356                 return iprop->get(ptr);
2357         else if (iprop->get_ex)
2358                 return iprop->get_ex(ptr, prop);
2359         else
2360                 return iprop->defaultvalue;
2361 }
2362
2363 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2364 {
2365         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2366         IDProperty *idprop;
2367
2368         BLI_assert(RNA_property_type(prop) == PROP_INT);
2369         BLI_assert(RNA_property_array_check(prop) == false);
2370         /* useful to check on bad values but set function should clamp */
2371         /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
2372
2373         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2374                 RNA_property_int_clamp(ptr, prop, &value);
2375                 IDP_Int(idprop) = value;
2376                 rna_idproperty_touch(idprop);
2377         }
2378         else if (iprop->set)
2379                 iprop->set(ptr, value);
2380         else if (iprop->set_ex)
2381                 iprop->set_ex(ptr, prop, value);
2382         else if (prop->flag & PROP_EDITABLE) {
2383                 IDPropertyTemplate val = {0};
2384                 IDProperty *group;
2385
2386                 RNA_property_int_clamp(ptr, prop, &value);
2387
2388                 val.i = value;
2389
2390                 group = RNA_struct_idprops(ptr, 1);
2391                 if (group)
2392                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2393         }
2394 }
2395
2396 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2397 {
2398         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2399         IDProperty *idprop;
2400
2401         BLI_assert(RNA_property_type(prop) == PROP_INT);
2402         BLI_assert(RNA_property_array_check(prop) != false);
2403
2404         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2405                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2406                 if (prop->arraydimension == 0)
2407                         values[0] = RNA_property_int_get(ptr, prop);
2408                 else
2409                         memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2410         }
2411         else if (prop->arraydimension == 0)
2412                 values[0] = RNA_property_int_get(ptr, prop);
2413         else if (iprop->getarray)
2414                 iprop->getarray(ptr, values);
2415         else if (iprop->getarray_ex)
2416                 iprop->getarray_ex(ptr, prop, values);
2417         else if (iprop->defaultarray)
2418                 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2419         else
2420                 memset(values, 0, sizeof(int) * prop->totarraylength);
2421 }
2422
2423 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
2424 {
2425         const int array_len = RNA_property_array_length(ptr, prop);
2426
2427         if (array_len <= 0) {
2428                 values[0] = 0;
2429                 values[1] = 0;
2430         }
2431         else if (array_len == 1) {
2432                 RNA_property_int_get_array(ptr, prop, values);
2433                 values[1] = values[0];
2434         }
2435         else {
2436                 int arr_stack[32];
2437                 int *arr;
2438                 int i;
2439
2440                 if (array_len > 32) {
2441                         arr = MEM_mallocN(sizeof(int) * array_len, __func__);
2442                 }
2443                 else {
2444                         arr = arr_stack;
2445                 }
2446
2447                 RNA_property_int_get_array(ptr, prop, arr);
2448                 values[0] = values[1] = arr[0];
2449                 for (i = 1; i < array_len; i++) {
2450                         values[0] = MIN2(values[0], arr[i]);
2451                         values[1] = MAX2(values[1], arr[i]);
2452                 }
2453
2454                 if (arr != arr_stack) {
2455                         MEM_freeN(arr);
2456                 }
2457         }
2458 }
2459
2460 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2461 {
2462         int tmp[RNA_MAX_ARRAY_LENGTH];
2463         int len = rna_ensure_property_array_length(ptr, prop);
2464
2465         BLI_assert(RNA_property_type(prop) == PROP_INT);
2466         BLI_assert(RNA_property_array_check(prop) != false);
2467         BLI_assert(index >= 0);
2468         BLI_assert(index < len);
2469
2470         if (len <= RNA_MAX_ARRAY_LENGTH) {
2471                 RNA_property_int_get_array(ptr, prop, tmp);
2472                 return tmp[index];
2473         }
2474         else {
2475                 int *tmparray, value;
2476
2477                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2478                 RNA_property_int_get_array(ptr, prop, tmparray);
2479                 value = tmparray[index];
2480                 MEM_freeN(tmparray);
2481
2482                 return value;
2483         }
2484 }
2485
2486 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2487 {
2488         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2489         IDProperty *idprop;
2490
2491         BLI_assert(RNA_property_type(prop) == PROP_INT);
2492         BLI_assert(RNA_property_array_check(prop) != false);
2493
2494         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2495                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2496                 if (prop->arraydimension == 0)
2497                         IDP_Int(idprop) = values[0];
2498                 else
2499                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2500
2501                 rna_idproperty_touch(idprop);
2502         }
2503         else if (prop->arraydimension == 0)
2504                 RNA_property_int_set(ptr, prop, values[0]);
2505         else if (iprop->setarray)
2506                 iprop->setarray(ptr, values);
2507         else if (iprop->setarray_ex)
2508                 iprop->setarray_ex(ptr, prop, values);
2509         else if (prop->flag & PROP_EDITABLE) {
2510                 IDPropertyTemplate val = {0};
2511                 IDProperty *group;
2512
2513                 /* TODO: RNA_property_int_clamp_array(ptr, prop, &value); */
2514
2515                 val.array.len = prop->totarraylength;
2516                 val.array.type = IDP_INT;
2517
2518                 group = RNA_struct_idprops(ptr, 1);
2519                 if (group) {
2520                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2521                         IDP_AddToGroup(group, idprop);
2522                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2523                 }
2524         }
2525 }
2526
2527 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2528 {
2529         int tmp[RNA_MAX_ARRAY_LENGTH];
2530         int len = rna_ensure_property_array_length(ptr, prop);
2531
2532         BLI_assert(RNA_property_type(prop) == PROP_INT);
2533         BLI_assert(RNA_property_array_check(prop) != false);
2534         BLI_assert(index >= 0);
2535         BLI_assert(index < len);
2536
2537         if (len <= RNA_MAX_ARRAY_LENGTH) {
2538                 RNA_property_int_get_array(ptr, prop, tmp);
2539                 tmp[index] = value;
2540                 RNA_property_int_set_array(ptr, prop, tmp);
2541         }
2542         else {
2543                 int *tmparray;
2544
2545                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2546                 RNA_property_int_get_array(ptr, prop, tmparray);
2547                 tmparray[index] = value;
2548                 RNA_property_int_set_array(ptr, prop, tmparray);
2549                 MEM_freeN(tmparray);
2550         }
2551 }
2552
2553 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2554 {
2555         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2556         return iprop->defaultvalue;
2557 }
2558
2559 void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2560 {
2561         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2562         
2563         BLI_assert(RNA_property_type(prop) == PROP_INT);
2564         BLI_assert(RNA_property_array_check(prop) != false);
2565
2566         if (prop->arraydimension == 0)
2567                 values[0] = iprop->defaultvalue;
2568         else if (iprop->defaultarray)
2569                 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2570         else
2571                 memset(values, 0, sizeof(int) * prop->totarraylength);
2572 }
2573
2574 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2575 {
2576         int tmp[RNA_MAX_ARRAY_LENGTH];
2577         int len = rna_ensure_property_array_length(ptr, prop);
2578
2579         BLI_assert(RNA_property_type(prop) == PROP_INT);
2580         BLI_assert(RNA_property_array_check(prop) != false);
2581         BLI_assert(index >= 0);
2582         BLI_assert(index < prop->totarraylength);
2583
2584         if (len <= RNA_MAX_ARRAY_LENGTH) {
2585                 RNA_property_int_get_default_array(ptr, prop, tmp);
2586                 return tmp[index];
2587         }
2588         else {
2589                 int *tmparray, value;
2590
2591                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2592                 RNA_property_int_get_default_array(ptr, prop, tmparray);
2593                 value = tmparray[index];
2594                 MEM_freeN(tmparray);
2595
2596                 return value;
2597         }
2598 }
2599
2600 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
2601 {
2602         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2603         IDProperty *idprop;
2604
2605         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2606         BLI_assert(RNA_property_array_check(prop) == false);
2607
2608         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2609                 if (idprop->type == IDP_FLOAT)
2610                         return IDP_Float(idprop);
2611                 else
2612                         return (float)IDP_Double(idprop);
2613         }
2614         else if (fprop->get)
2615                 return fprop->get(ptr);
2616         else if (fprop->get_ex)
2617                 return fprop->get_ex(ptr, prop);
2618         else
2619                 return fprop->defaultvalue;
2620 }
2621
2622 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
2623 {
2624         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2625         IDProperty *idprop;
2626
2627         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2628         BLI_assert(RNA_property_array_check(prop) == false);
2629         /* useful to check on bad values but set function should clamp */
2630         /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
2631
2632         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2633                 RNA_property_float_clamp(ptr, prop, &value);
2634                 if (idprop->type == IDP_FLOAT)
2635                         IDP_Float(idprop) = value;
2636                 else
2637                         IDP_Double(idprop) = value;
2638
2639                 rna_idproperty_touch(idprop);
2640         }
2641         else if (fprop->set) {
2642                 fprop->set(ptr, value);
2643         }
2644         else if (fprop->set_ex) {
2645                 fprop->set_ex(ptr, prop, value);
2646         }
2647         else if (prop->flag & PROP_EDITABLE) {
2648                 IDPropertyTemplate val = {0};
2649                 IDProperty *group;
2650
2651                 RNA_property_float_clamp(ptr, prop, &value);
2652
2653                 val.f = value;
2654
2655                 group = RNA_struct_idprops(ptr, 1);
2656                 if (group)
2657                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
2658         }
2659 }
2660
2661 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
2662 {
2663         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2664         IDProperty *idprop;
2665         int i;
2666
2667         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2668         BLI_assert(RNA_property_array_check(prop) != false);
2669
2670         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2671                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2672                 if (prop->arraydimension == 0)
2673                         values[0] = RNA_property_float_get(ptr, prop);
2674                 else if (idprop->subtype == IDP_FLOAT) {
2675                         memcpy(values, IDP_Array(idprop), sizeof(float) * idprop->len);
2676                 }
2677                 else {
2678                         for (i = 0; i < idprop->len; i++)
2679                                 values[i] =  (float)(((double *)IDP_Array(idprop))[i]);
2680                 }
2681         }
2682         else if (prop->arraydimension == 0)
2683                 values[0] = RNA_property_float_get(ptr, prop);
2684         else if (fprop->getarray)
2685                 fprop->getarray(ptr, values);
2686         else if (fprop->getarray_ex)
2687                 fprop->getarray_ex(ptr, prop, values);
2688         else if (fprop->defaultarray)
2689                 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2690         else
2691                 memset(values, 0, sizeof(float) * prop->totarraylength);
2692 }
2693
2694 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
2695 {
2696         const int array_len = RNA_property_array_length(ptr, prop);
2697
2698         if (array_len <= 0) {
2699                 values[0] = 0.0f;
2700                 values[1] = 0.0f;
2701         }
2702         else if (array_len == 1) {
2703                 RNA_property_float_get_array(ptr, prop, values);
2704                 values[1] = values[0];
2705         }
2706         else {
2707                 float arr_stack[32];
2708                 float *arr;
2709                 int i;
2710
2711                 if (array_len > 32) {
2712                         arr = MEM_mallocN(sizeof(float) * array_len, __func__);
2713                 }
2714                 else {
2715                         arr = arr_stack;
2716                 }
2717
2718                 RNA_property_float_get_array(ptr, prop, arr);
2719                 values[0] = values[1] = arr[0];
2720                 for (i = 1; i < array_len; i++) {
2721                         values[0] = MIN2(values[0], arr[i]);
2722                         values[1] = MAX2(values[1], arr[i]);
2723                 }
2724
2725                 if (arr != arr_stack) {
2726                         MEM_freeN(arr);
2727                 }
2728         }
2729 }
2730
2731 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2732 {
2733         float tmp[RNA_MAX_ARRAY_LENGTH];
2734         int len = rna_ensure_property_array_length(ptr, prop);
2735
2736         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2737         BLI_assert(RNA_property_array_check(prop) != false);
2738         BLI_assert(index >= 0);
2739         BLI_assert(index < len);
2740
2741         if (len <= RNA_MAX_ARRAY_LENGTH) {
2742                 RNA_property_float_get_array(ptr, prop, tmp);
2743                 return tmp[index];
2744         }
2745         else {
2746                 float *tmparray, value;
2747
2748                 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2749                 RNA_property_float_get_array(ptr, prop, tmparray);
2750                 value = tmparray[index];
2751                 MEM_freeN(tmparray);
2752
2753                 return value;
2754         }
2755 }
2756
2757 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
2758 {
2759         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2760         IDProperty *idprop;
2761         int i;
2762
2763         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2764         BLI_assert(RNA_property_array_check(prop) != false);
2765
2766         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2767                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2768                 if (prop->arraydimension == 0) {
2769                         if (idprop->type == IDP_FLOAT)
2770                                 IDP_Float(idprop) = values[0];
2771                         else
2772                                 IDP_Double(idprop) = values[0];
2773                 }
2774                 else if (idprop->subtype == IDP_FLOAT) {
2775                         memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2776                 }
2777                 else {
2778                         for (i = 0; i < idprop->len; i++)
2779                                 ((double *)IDP_Array(idprop))[i] = values[i];
2780                 }
2781
2782                 rna_idproperty_touch(idprop);
2783         }
2784         else if (prop->arraydimension == 0)
2785                 RNA_property_float_set(ptr, prop, values[0]);
2786         else if (fprop->setarray) {
2787                 fprop->setarray(ptr, values);
2788         }
2789         else if (fprop->setarray_ex) {
2790                 fprop->setarray_ex(ptr, prop, values);
2791         }
2792         else if (prop->flag & PROP_EDITABLE) {
2793                 IDPropertyTemplate val = {0};
2794                 IDProperty *group;
2795
2796                 /* TODO: RNA_property_float_clamp_array(ptr, prop, &value); */
2797
2798                 val.array.len = prop->totarraylength;
2799                 val.array.type = IDP_FLOAT;
2800
2801                 group = RNA_struct_idprops(ptr, 1);
2802                 if (group) {
2803                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2804                         IDP_AddToGroup(group, idprop);
2805                         memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2806                 }
2807         }
2808 }
2809
2810 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
2811 {
2812         float tmp[RNA_MAX_ARRAY_LENGTH];
2813         int len = rna_ensure_property_array_length(ptr, prop);
2814
2815         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2816         BLI_assert(RNA_property_array_check(prop) != false);
2817         BLI_assert(index >= 0);
2818         BLI_assert(index < len);
2819
2820         if (len <= RNA_MAX_ARRAY_LENGTH) {
2821                 RNA_property_float_get_array(ptr, prop, tmp);
2822                 tmp[index] = value;
2823                 RNA_property_float_set_array(ptr, prop, tmp);
2824         }
2825         else {
2826                 float *tmparray;
2827
2828                 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2829                 RNA_property_float_get_array(ptr, prop, tmparray);
2830                 tmparray[index] = value;
2831                 RNA_property_float_set_array(ptr, prop, tmparray);
2832                 MEM_freeN(tmparray);
2833         }
2834 }
2835
2836 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2837 {
2838         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
2839
2840         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2841         BLI_assert(RNA_property_array_check(prop) == false);
2842
2843         return fprop->defaultvalue;
2844 }
2845
2846 void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, float *values)
2847 {
2848         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
2849         
2850         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2851         BLI_assert(RNA_property_array_check(prop) != false);
2852
2853         if (prop->arraydimension == 0)
2854                 values[0] = fprop->defaultvalue;
2855         else if (fprop->defaultarray)
2856                 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2857         else
2858                 memset(values, 0, sizeof(float) * prop->totarraylength);
2859 }
2860
2861 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2862 {
2863         float tmp[RNA_MAX_ARRAY_LENGTH];
2864         int len = rna_ensure_property_array_length(ptr, prop);
2865
2866         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2867         BLI_assert(RNA_property_array_check(prop) != false);
2868         BLI_assert(index >= 0);
2869         BLI_assert(index < prop->totarraylength);
2870
2871         if (len <= RNA_MAX_ARRAY_LENGTH) {
2872                 RNA_property_float_get_default_array(ptr, prop, tmp);
2873                 return tmp[index];
2874         }
2875         else {
2876                 float *tmparray, value;
2877
2878                 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2879                 RNA_property_float_get_default_array(ptr, prop, tmparray);
2880                 value = tmparray[index];
2881                 MEM_freeN(tmparray);
2882
2883                 return value;
2884         }
2885 }
2886
2887 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
2888 {
2889         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2890         IDProperty *idprop;
2891
2892         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2893
2894         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2895                 /* editing bytes is not 100% supported
2896                  * since they can contain NIL chars */
2897                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2898                         memcpy(value, IDP_String(idprop), idprop->len);
2899                         value[idprop->len] = '\0';
2900                 }
2901                 else {
2902                         memcpy(value, IDP_String(idprop), idprop->len);
2903                 }
2904         }
2905         else if (sprop->get) {
2906                 sprop->get(ptr, value);
2907         }
2908         else if (sprop->get_ex) {
2909                 sprop->get_ex(ptr, prop, value);
2910         }
2911         else {
2912                 strcpy(value, sprop->defaultvalue);
2913         }
2914 }
2915
2916 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop,
2917                                     char *fixedbuf, int fixedlen, int *r_len)
2918 {
2919         char *buf;
2920         int length;
2921
2922         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2923
2924         length = RNA_property_string_length(ptr, prop);
2925
2926         if (length + 1 < fixedlen)
2927                 buf = fixedbuf;
2928         else
2929                 buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
2930
2931 #ifndef NDEBUG
2932         /* safety check to ensure the string is actually set */
2933         buf[length] = 255;
2934 #endif
2935
2936         RNA_property_string_get(ptr, prop, buf);
2937
2938 #ifndef NDEBUG
2939         BLI_assert(buf[length] == '\0');
2940 #endif
2941
2942         if (r_len) {
2943                 *r_len = length;
2944         }
2945
2946         return buf;
2947 }
2948
2949 /* this is the length without \0 terminator */
2950 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
2951 {
2952         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2953         IDProperty *idprop;
2954
2955         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2956
2957         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2958                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2959                         return idprop->len;
2960                 }
2961                 else {
2962 #ifndef NDEBUG
2963                         /* these _must_ stay in sync */
2964                         BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
2965 #endif
2966                         return idprop->len - 1;
2967                 }
2968         }
2969         else if (sprop->length)
2970                 return sprop->length(ptr);
2971         else if (sprop->length_ex)
2972                 return sprop->length_ex(ptr, prop);
2973         else
2974                 return strlen(sprop->defaultvalue);
2975 }
2976
2977 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
2978 {
2979         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2980         IDProperty *idprop;
2981
2982         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2983
2984         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2985                 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
2986                 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
2987                 rna_idproperty_touch(idprop);
2988         }
2989         else if (sprop->set)
2990                 sprop->set(ptr, value);  /* set function needs to clamp its self */
2991         else if (sprop->set_ex)
2992                 sprop->set_ex(ptr, prop, value);  /* set function needs to clamp its self */
2993         else if (prop->flag & PROP_EDITABLE) {
2994                 IDProperty *group;
2995
2996                 group = RNA_struct_idprops(ptr, 1);
2997                 if (group)
2998                         IDP_AddToGroup(group, IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop)));
2999         }
3000 }
3001
3002 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
3003 {
3004         StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
3005
3006         BLI_assert(RNA_property_type(prop) == PROP_STRING);
3007
3008         strcpy(value, sprop->defaultvalue);
3009 }
3010
3011 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
3012 {
3013         char *buf;
3014         int length;
3015
3016         BLI_assert(RNA_property_type(prop) == PROP_STRING);
3017
3018         length = RNA_property_string_default_length(ptr, prop);
3019
3020         if (length + 1 < fixedlen)
3021                 buf = fixedbuf;
3022         else
3023                 buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
3024
3025         RNA_property_string_get_default(ptr, prop, buf);
3026
3027         return buf;
3028 }
3029
3030 /* this is the length without \0 terminator */
3031 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3032 {
3033         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
3034
3035         BLI_assert(RNA_property_type(prop) == PROP_STRING);
3036
3037         return strlen(sprop->defaultvalue);
3038 }
3039
3040 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
3041 {
3042         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3043         IDProperty *idprop;
3044
3045         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3046
3047         if ((idprop = rna_idproperty_check(&prop, ptr)))
3048                 return IDP_Int(idprop);
3049         else if (eprop->get)
3050                 return eprop->get(ptr);
3051         else if (eprop->get_ex)
3052                 return eprop->get_ex(ptr, prop);
3053         else
3054                 return eprop->defaultvalue;
3055 }
3056
3057 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
3058 {
3059         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3060         IDProperty *idprop;
3061
3062         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3063
3064         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3065                 IDP_Int(idprop) = value;
3066                 rna_idproperty_touch(idprop);
3067         }
3068         else if (eprop->set) {
3069                 eprop->set(ptr, value);
3070         }
3071         else if (eprop->set_ex) {
3072                 eprop->set_ex(ptr, prop, value);
3073         }
3074         else if (prop->flag & PROP_EDITABLE) {
3075                 IDPropertyTemplate val = {0};
3076                 IDProperty *group;
3077
3078                 val.i = value;
3079
3080                 group = RNA_struct_idprops(ptr, 1);
3081                 if (group)
3082                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
3083         }
3084 }
3085
3086 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3087 {
3088         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
3089
3090         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3091
3092         return eprop->defaultvalue;
3093 }
3094
3095 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
3096 {
3097         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3098
3099         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3100
3101         return eprop->py_data;
3102 }
3103
3104 /**
3105  * Get the value of the item that is \a step items away from \a from_value.
3106  *
3107  * \param from_value: Item value to start stepping from.
3108  * \param step: Absolute value defines step size, sign defines direction.
3109  *              E.g to get the next item, pass 1, for the previous -1.
3110  */
3111 int RNA_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
3112 {
3113         const EnumPropertyItem *item_array;
3114         int totitem;
3115         bool free;
3116         int result_value = from_value;
3117         int i, i_init;
3118         int single_step = (step < 0) ? -1 : 1;
3119         int step_tot = 0;
3120
3121         RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
3122         i = RNA_enum_from_value(item_array, from_value);
3123         i_init = i;
3124
3125         do {
3126                 i = mod_i(i + single_step, totitem);
3127                 if (item_array[i].identifier[0]) {
3128                         step_tot += single_step;
3129                 }
3130         } while ((i != i_init) && (step_tot != step));
3131
3132         if (i != i_init) {
3133                 result_value = item_array[i].value;
3134         }
3135
3136         if (free) {
3137                 MEM_freeN((void *)item_array);
3138         }
3139
3140         return result_value;
3141 }
3142
3143 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
3144 {
3145         PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3146         IDProperty *idprop;
3147
3148         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3149
3150         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3151                 pprop = (PointerPropertyRNA *)prop;
3152
3153                 if (RNA_struct_is_ID(pprop->type)) {
3154                         return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop));
3155                 }
3156
3157                 /* for groups, data is idprop itself */
3158                 if (pprop->typef)
3159                         return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
3160                 else
3161                         return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
3162         }
3163         else if (pprop->get) {
3164                 return pprop->get(ptr);
3165         }
3166         else if (prop->flag & PROP_IDPROPERTY) {
3167                 /* XXX temporary hack to add it automatically, reading should
3168                  * never do any write ops, to ensure thread safety etc .. */
3169                 RNA_property_pointer_add(ptr, prop);
3170                 return RNA_property_pointer_get(ptr, prop);
3171         }
3172         else {
3173                 return PointerRNA_NULL;
3174         }
3175 }
3176
3177 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
3178 {
3179         PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3180         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3181
3182         /* Check types */
3183         if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
3184                 printf("%s: expected %s type, not %s.\n", __func__, pprop->type->identifier, ptr_value.type->identifier);
3185                 return;
3186         }
3187
3188         /* RNA */
3189         if (pprop->set &&
3190             !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
3191             !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
3192         {
3193                 pprop->set(ptr, ptr_value);
3194         }
3195         /* IDProperty */
3196         else if (prop->flag & PROP_EDITABLE) {
3197                 IDPropertyTemplate val = {0};
3198                 IDProperty *group;
3199
3200                 val.id = ptr_value.data;
3201
3202                 group = RNA_struct_idprops(ptr, true);
3203                 if (group) {
3204                         IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier));
3205                 }
3206         }
3207 }
3208
3209 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
3210 {
3211         /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
3212
3213         /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
3214
3215         return PointerRNA_NULL; /* FIXME: there has to be a way... */
3216 }
3217
3218 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
3219 {
3220         /*IDProperty *idprop;*/
3221
3222         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3223
3224         if ((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
3225                 /* already exists */
3226         }
3227         else if (prop->flag & PROP_IDPROPERTY) {
3228                 IDPropertyTemplate val = {0};
3229                 IDProperty *group;
3230
3231                 val.i = 0;
3232
3233                 group = RNA_struct_idprops(ptr, 1);
3234                 if (group)
3235                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
3236         }
3237         else
3238                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
3239 }
3240
3241 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
3242 {
3243         IDProperty *idprop, *group;
3244
3245         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3246
3247         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3248                 group = RNA_struct_idprops(ptr, 0);
3249                 
3250                 if (group) {
3251                         IDP_FreeFromGroup(group, idprop);
3252                 }
3253         }
3254         else
3255                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
3256 }
3257
3258 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
3259 {
3260         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
3261
3262         iter->ptr.data = rna_iterator_array_get(iter);
3263         iter->ptr.type = cprop->item_type;
3264         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
3265 }
3266
3267 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
3268 {
3269         IDProperty *idprop;
3270
3271         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3272
3273         memset(iter, 0, sizeof(*iter));
3274
3275         if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
3276                 iter->parent = *ptr;
3277                 iter->prop = prop;
3278
3279                 if (idprop)
3280                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
3281                 else
3282                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
3283
3284                 if (iter->valid)
3285                         rna_property_collection_get_idp(iter);
3286
3287                 iter->idprop = 1;
3288         }
3289         else {
3290                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3291                 cprop->begin(iter, ptr);
3292         }
3293 }
3294
3295 void RNA_property_collection_next(CollectionPropertyIterator *iter)
3296 {
3297         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3298
3299         if (iter->idprop) {
3300                 rna_iterator_array_next(iter);
3301
3302                 if (iter->valid)
3303                         rna_property_collection_get_idp(iter);
3304         }
3305         else
3306                 cprop->next(iter);
3307 }
3308
3309 void RNA_property_collection_skip(CollectionPropertyIterator *iter, int num)
3310 {
3311         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3312         int i;
3313
3314         if (num > 1 && (iter->idprop || (cprop->property.flag_internal & PROP_INTERN_RAW_ARRAY))) {
3315                 /* fast skip for array */
3316                 ArrayIterator *internal = &iter->internal.array;
3317
3318                 if (!internal->skip) {
3319                         internal->ptr += internal->itemsize * (num - 1);
3320                         iter->valid = (internal->ptr < internal->endptr);
3321                         if (iter->valid)
3322                                 RNA_property_collection_next(iter);
3323                         return;
3324                 }
3325         }
3326
3327         /* slow iteration otherwise */
3328         for (i = 0; i < num && iter->valid; i++)
3329                 RNA_property_collection_next(iter);
3330 }
3331
3332 void RNA_property_collection_end(CollectionPropertyIterator *iter)
3333 {
3334         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3335
3336         if (iter->idprop)
3337                 rna_iterator_array_end(iter);
3338         else
3339                 cprop->end(iter);
3340 }
3341
3342 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
3343 {
3344         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3345         IDProperty *idprop;
3346
3347         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3348
3349         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3350                 return idprop->len;
3351         }
3352         else if (cprop->length) {
3353                 return cprop->length(ptr);
3354         }
3355         else {
3356                 CollectionPropertyIterator iter;
3357                 int length = 0;
3358
3359                 RNA_property_collection_begin(ptr, prop, &iter);
3360                 for (; iter.valid; RNA_property_collection_next(&iter))
3361                         length++;
3362                 RNA_property_collection_end(&iter);
3363
3364                 return length;
3365         }
3366 }
3367
3368 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
3369 {
3370         IDProperty *idprop;
3371 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
3372
3373         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3374
3375         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3376                 IDPropertyTemplate val = {0};
3377                 IDProperty *item;
3378
3379                 item = IDP_New(IDP_GROUP, &val, "");
3380                 IDP_AppendArray(idprop, item);
3381                 /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory  */
3382                 MEM_freeN(item);
3383                 rna_idproperty_touch(idprop);
3384         }
3385         else if (prop->flag & PROP_IDPROPERTY) {
3386                 IDProperty *group, *item;
3387                 IDPropertyTemplate val = {0};
3388
3389                 group = RNA_struct_idprops(ptr, 1);
3390                 if (group) {
3391                         idprop = IDP_NewIDPArray(prop->identifier);
3392                         IDP_AddToGroup(group, idprop);
3393
3394                         item = IDP_New(IDP_GROUP, &val, "");
3395                         IDP_AppendArray(idprop, item);
3396                         /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory */
3397                         MEM_freeN(item);
3398                 }
3399         }
3400
3401         /* py api calls directly */
3402 #if 0
3403         else if (cprop->add) {
3404                 if (!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
3405                         ParameterList params;
3406                         RNA_parameter_list_create(&params, ptr, cprop->add);
3407                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
3408                         RNA_parameter_list_free(&params);
3409                 }
3410         }
3411 #if 0
3412         else {
3413                 printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);
3414         }
3415 #endif
3416 #endif
3417
3418         if (r_ptr) {
3419                 if (idprop) {
3420                         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;