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