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