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