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