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