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