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