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