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