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