Give Sensors/Controllers/Actuators more sensible names when they're created
[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 int RNA_property_string_maxlength(PropertyRNA *prop)
965 {
966         StringPropertyRNA *sprop= (StringPropertyRNA*)rna_ensure_property(prop);
967         return sprop->maxlength;
968 }
969
970 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
971 {
972         prop= rna_ensure_property(prop);
973
974         if(prop->type == PROP_POINTER) {
975                 PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
976
977                 if(pprop->typef)
978                         return pprop->typef(ptr);
979                 else if(pprop->type)
980                         return pprop->type;
981         }
982         else if(prop->type == PROP_COLLECTION) {
983                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
984
985                 if(cprop->item_type)
986                         return cprop->item_type;
987         }
988
989         return &RNA_UnknownType;
990 }
991
992 /* Reuse for dynamic types  */
993 EnumPropertyItem DummyRNA_NULL_items[] = {
994         {0, NULL, 0, NULL, NULL}
995 };
996
997 /* Reuse for dynamic types with default value */
998 EnumPropertyItem DummyRNA_DEFAULT_items[] = {
999         {0, "DEFAULT", 0, "Default", ""},
1000         {0, NULL, 0, NULL, NULL}
1001 };
1002
1003 void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free)
1004 {
1005         EnumPropertyRNA *eprop= (EnumPropertyRNA*)rna_ensure_property(prop);
1006
1007         *free= 0;
1008
1009         if(eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1010                 int tot= 0;
1011
1012                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1013                         *item= eprop->itemf(NULL, ptr, free);
1014                 else
1015                         *item= eprop->itemf(C, ptr, free);
1016
1017                 if(totitem) {
1018                         if(*item) {
1019                                 for( ; (*item)[tot].identifier; tot++);
1020                         }
1021
1022                         *totitem= tot;
1023                 }
1024         }
1025         else {
1026                 *item= eprop->item;
1027                 if(totitem)
1028                         *totitem= eprop->totitem;
1029         }
1030 }
1031
1032 int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
1033 {       
1034         EnumPropertyItem *item, *item_array;
1035         int free, found;
1036         
1037         RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free);
1038         
1039         for(item= item_array; item->identifier; item++) {
1040                 if(item->identifier[0] && strcmp(item->identifier, identifier)==0) {
1041                         *value = item->value;
1042                         break;
1043                 }
1044         }
1045         
1046         found= (item->identifier != NULL); /* could be alloc'd, assign before free */
1047
1048         if(free)
1049                 MEM_freeN(item_array);
1050
1051         return found;
1052 }
1053
1054 int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier)
1055 {
1056         for (; item->identifier; item++) {
1057                 if(item->identifier[0] && item->value==value) {
1058                         *identifier = item->identifier;
1059                         return 1;
1060                 }
1061         }
1062         return 0;
1063 }
1064
1065 int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier)
1066 {
1067         int index= 0;
1068         for (; item->identifier; item++) {
1069                 if(item->identifier[0] && item->value & value) {
1070                         identifier[index++] = item->identifier;
1071                 }
1072         }
1073         identifier[index]= NULL;
1074         return index;
1075 }
1076
1077 int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name)
1078 {
1079         for (; item->identifier; item++) {
1080                 if(item->identifier[0] && item->value==value) {
1081                         *name = item->name;
1082                         return 1;
1083                 }
1084         }
1085         return 0;
1086 }
1087
1088 int RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
1089 {       
1090         EnumPropertyItem *item= NULL;
1091         int result, free;
1092         
1093         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1094         if(item) {
1095                 result= RNA_enum_identifier(item, value, identifier);
1096                 if(free)
1097                         MEM_freeN(item);
1098
1099                 return result;
1100         }
1101         return 0;
1102 }
1103
1104 int RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1105 {       
1106         EnumPropertyItem *item= NULL;
1107         int result, free;
1108         
1109         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1110         if(item) {
1111                 result= RNA_enum_name(item, value, name);
1112                 if(free)
1113                         MEM_freeN(item);
1114                 
1115                 return result;
1116         }
1117         return 0;
1118 }
1119
1120 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
1121 {
1122         EnumPropertyItem *item= NULL;
1123         int result, free;
1124
1125         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1126         if(item) {
1127                 result= RNA_enum_bitflag_identifiers(item, value, identifier);
1128                 if(free)
1129                         MEM_freeN(item);
1130
1131                 return result;
1132         }
1133         return 0;
1134 }
1135
1136 const char *RNA_property_ui_name(PropertyRNA *prop)
1137 {
1138         return rna_ensure_property_name(prop);
1139 }
1140
1141 const char *RNA_property_ui_description(PropertyRNA *prop)
1142 {
1143         return rna_ensure_property_description(prop);
1144 }
1145
1146 int RNA_property_ui_icon(PropertyRNA *prop)
1147 {
1148         return rna_ensure_property(prop)->icon;
1149 }
1150
1151 int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1152 {
1153         ID *id= ptr->id.data;
1154         int flag;
1155
1156         prop= rna_ensure_property(prop);
1157         flag= prop->editable ? prop->editable(ptr) : prop->flag;
1158         return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
1159 }
1160
1161 int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
1162 {
1163         int flag;
1164
1165         prop= rna_ensure_property(prop);
1166         flag= prop->editable ? prop->editable(ptr) : prop->flag;
1167         return (flag & PROP_EDITABLE);
1168 }
1169
1170 /* same as RNA_property_editable(), except this checks individual items in an array */
1171 int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1172 {
1173         ID *id;
1174         int flag;
1175
1176         prop= rna_ensure_property(prop);
1177
1178         flag= prop->flag;
1179         
1180         if(prop->editable)
1181                 flag &= prop->editable(ptr);
1182
1183         if (prop->itemeditable)
1184                 flag &= prop->itemeditable(ptr, index);
1185
1186         id= ptr->id.data;
1187
1188         return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
1189 }
1190
1191 int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1192 {
1193         /* check that base ID-block can support animation data */
1194         if (!id_type_can_have_animdata(ptr->id.data))
1195                 return 0;
1196         
1197         prop= rna_ensure_property(prop);
1198
1199         if(!(prop->flag & PROP_ANIMATABLE))
1200                 return 0;
1201
1202         return (prop->flag & PROP_EDITABLE);
1203 }
1204
1205 int RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
1206 {
1207         /* would need to ask animation system */
1208
1209         return 0;
1210 }
1211
1212 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1213 {
1214         int is_rna = (prop->magic == RNA_MAGIC);
1215         prop= rna_ensure_property(prop);
1216
1217         if(is_rna) {
1218                 if(prop->update) {
1219                         /* ideally no context would be needed for update, but there's some
1220                            parts of the code that need it still, so we have this exception */
1221                         if(prop->flag & PROP_CONTEXT_UPDATE) {
1222                                 if(C) ((ContextUpdateFunc)prop->update)(C, ptr);
1223                         }
1224                         else
1225                                 prop->update(bmain, scene, ptr);
1226                 }
1227                 if(prop->noteflag)
1228                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1229         }
1230         else {
1231                 /* WARNING! This is so property drivers update the display!
1232                  * not especially nice  */
1233                 DAG_id_flush_update(ptr->id.data, OB_RECALC);
1234                 WM_main_add_notifier(NC_WINDOW, NULL);
1235         }
1236
1237 }
1238
1239 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1240 {
1241         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
1242 }
1243
1244 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1245 {
1246         rna_property_update(NULL, bmain, scene, ptr, prop);
1247 }
1248
1249 /* Property Data */
1250
1251 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
1252 {
1253         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1254         IDProperty *idprop;
1255
1256         if((idprop=rna_idproperty_check(&prop, ptr)))
1257                 return IDP_Int(idprop);
1258         else if(bprop->get)
1259                 return bprop->get(ptr);
1260         else
1261                 return bprop->defaultvalue;
1262 }
1263
1264 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1265 {
1266         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1267         IDProperty *idprop;
1268
1269         /* just incase other values are passed */
1270         if(value) value= 1;
1271
1272         if((idprop=rna_idproperty_check(&prop, ptr)))
1273                 IDP_Int(idprop)= value;
1274         else if(bprop->set)
1275                 bprop->set(ptr, value);
1276         else if(prop->flag & PROP_EDITABLE) {
1277                 IDPropertyTemplate val = {0};
1278                 IDProperty *group;
1279
1280                 val.i= value;
1281
1282                 group= RNA_struct_idproperties(ptr, 1);
1283                 if(group)
1284                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1285         }
1286 }
1287
1288 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1289 {
1290         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1291         IDProperty *idprop;
1292
1293         if((idprop=rna_idproperty_check(&prop, ptr))) {
1294                 if(prop->arraydimension == 0)
1295                         values[0]= RNA_property_boolean_get(ptr, prop);
1296                 else
1297                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
1298         }
1299         else if(prop->arraydimension == 0)
1300                 values[0]= RNA_property_boolean_get(ptr, prop);
1301         else if(bprop->getarray)
1302                 bprop->getarray(ptr, values);
1303         else if(bprop->defaultarray)
1304                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->totarraylength);
1305         else
1306                 memset(values, 0, sizeof(int)*prop->totarraylength);
1307 }
1308
1309 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1310 {
1311         int tmp[RNA_MAX_ARRAY_LENGTH];
1312         int len= rna_ensure_property_array_length(ptr, prop);
1313
1314         if(len <= RNA_MAX_ARRAY_LENGTH) {
1315                 RNA_property_boolean_get_array(ptr, prop, tmp);
1316                 return tmp[index];
1317         }
1318         else {
1319                 int *tmparray, value;
1320
1321                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_index");
1322                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1323                 value= tmparray[index];
1324                 MEM_freeN(tmparray);
1325
1326                 return value;
1327         }
1328 }
1329
1330 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1331 {
1332         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1333         IDProperty *idprop;
1334
1335         if((idprop=rna_idproperty_check(&prop, ptr))) {
1336                 if(prop->arraydimension == 0)
1337                         IDP_Int(idprop)= values[0];
1338                 else
1339                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1340         }
1341         else if(prop->arraydimension == 0)
1342                 RNA_property_boolean_set(ptr, prop, values[0]);
1343         else if(bprop->setarray)
1344                 bprop->setarray(ptr, values);
1345         else if(prop->flag & PROP_EDITABLE) {
1346                 IDPropertyTemplate val = {0};
1347                 IDProperty *group;
1348
1349                 val.array.len= prop->totarraylength;
1350                 val.array.type= IDP_INT;
1351
1352                 group= RNA_struct_idproperties(ptr, 1);
1353                 if(group) {
1354                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
1355                         IDP_AddToGroup(group, idprop);
1356                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1357                 }
1358         }
1359 }
1360
1361 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1362 {
1363         int tmp[RNA_MAX_ARRAY_LENGTH];
1364         int len= rna_ensure_property_array_length(ptr, prop);
1365
1366         if(len <= RNA_MAX_ARRAY_LENGTH) {
1367                 RNA_property_boolean_get_array(ptr, prop, tmp);
1368                 tmp[index]= value;
1369                 RNA_property_boolean_set_array(ptr, prop, tmp);
1370         }
1371         else {
1372                 int *tmparray;
1373
1374                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_index");
1375                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1376                 tmparray[index]= value;
1377                 RNA_property_boolean_set_array(ptr, prop, tmparray);
1378                 MEM_freeN(tmparray);
1379         }
1380 }
1381
1382 int RNA_property_boolean_get_default(PointerRNA *ptr, PropertyRNA *prop)
1383 {
1384         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1385         return bprop->defaultvalue;
1386 }
1387
1388 void RNA_property_boolean_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1389 {
1390         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1391         
1392         if(prop->arraydimension == 0)
1393                 values[0]= bprop->defaultvalue;
1394         else if(bprop->defaultarray)
1395                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->totarraylength);
1396         else
1397                 memset(values, 0, sizeof(int)*prop->totarraylength);
1398 }
1399
1400 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1401 {
1402         int tmp[RNA_MAX_ARRAY_LENGTH];
1403         int len= rna_ensure_property_array_length(ptr, prop);
1404
1405         if(len <= RNA_MAX_ARRAY_LENGTH) {
1406                 RNA_property_boolean_get_default_array(ptr, prop, tmp);
1407                 return tmp[index];
1408         }
1409         else {
1410                 int *tmparray, value;
1411
1412                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_default_index");
1413                 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
1414                 value= tmparray[index];
1415                 MEM_freeN(tmparray);
1416
1417                 return value;
1418         }
1419 }
1420
1421 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
1422 {
1423         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1424         IDProperty *idprop;
1425
1426         if((idprop=rna_idproperty_check(&prop, ptr)))
1427                 return IDP_Int(idprop);
1428         else if(iprop->get)
1429                 return iprop->get(ptr);
1430         else
1431                 return iprop->defaultvalue;
1432 }
1433
1434 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1435 {
1436         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1437         IDProperty *idprop;
1438
1439         if((idprop=rna_idproperty_check(&prop, ptr)))
1440                 IDP_Int(idprop)= value;
1441         else if(iprop->set)
1442                 iprop->set(ptr, value);
1443         else if(prop->flag & PROP_EDITABLE) {
1444                 IDPropertyTemplate val = {0};
1445                 IDProperty *group;
1446
1447                 val.i= value;
1448
1449                 group= RNA_struct_idproperties(ptr, 1);
1450                 if(group)
1451                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1452         }
1453 }
1454
1455 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1456 {
1457         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1458         IDProperty *idprop;
1459
1460         if((idprop=rna_idproperty_check(&prop, ptr))) {
1461                 if(prop->arraydimension == 0)
1462                         values[0]= RNA_property_int_get(ptr, prop);
1463                 else
1464                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
1465         }
1466         else if(prop->arraydimension == 0)
1467                 values[0]= RNA_property_int_get(ptr, prop);
1468         else if(iprop->getarray)
1469                 iprop->getarray(ptr, values);
1470         else if(iprop->defaultarray)
1471                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->totarraylength);
1472         else
1473                 memset(values, 0, sizeof(int)*prop->totarraylength);
1474 }
1475
1476 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1477 {
1478         int tmp[RNA_MAX_ARRAY_LENGTH];
1479         int len= rna_ensure_property_array_length(ptr, prop);
1480
1481         if(len <= RNA_MAX_ARRAY_LENGTH) {
1482                 RNA_property_int_get_array(ptr, prop, tmp);
1483                 return tmp[index];
1484         }
1485         else {
1486                 int *tmparray, value;
1487
1488                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_int_get_index");
1489                 RNA_property_int_get_array(ptr, prop, tmparray);
1490                 value= tmparray[index];
1491                 MEM_freeN(tmparray);
1492
1493                 return value;
1494         }
1495 }
1496
1497 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1498 {
1499         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1500         IDProperty *idprop;
1501
1502         if((idprop=rna_idproperty_check(&prop, ptr))) {
1503                 if(prop->arraydimension == 0)
1504                         IDP_Int(idprop)= values[0];
1505                 else
1506                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);\
1507         }
1508         else if(prop->arraydimension == 0)
1509                 RNA_property_int_set(ptr, prop, values[0]);
1510         else if(iprop->setarray)
1511                 iprop->setarray(ptr, values);
1512         else if(prop->flag & PROP_EDITABLE) {
1513                 IDPropertyTemplate val = {0};
1514                 IDProperty *group;
1515
1516                 val.array.len= prop->totarraylength;
1517                 val.array.type= IDP_INT;
1518
1519                 group= RNA_struct_idproperties(ptr, 1);
1520                 if(group) {
1521                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
1522                         IDP_AddToGroup(group, idprop);
1523                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1524                 }
1525         }
1526 }
1527
1528 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1529 {
1530         int tmp[RNA_MAX_ARRAY_LENGTH];
1531         int len= rna_ensure_property_array_length(ptr, prop);
1532
1533         if(len <= RNA_MAX_ARRAY_LENGTH) {
1534                 RNA_property_int_get_array(ptr, prop, tmp);
1535                 tmp[index]= value;
1536                 RNA_property_int_set_array(ptr, prop, tmp);
1537         }
1538         else {
1539                 int *tmparray;
1540
1541                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_int_get_index");
1542                 RNA_property_int_get_array(ptr, prop, tmparray);
1543                 tmparray[index]= value;
1544                 RNA_property_int_set_array(ptr, prop, tmparray);
1545                 MEM_freeN(tmparray);
1546         }
1547 }
1548
1549 int RNA_property_int_get_default(PointerRNA *ptr, PropertyRNA *prop)
1550 {
1551         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1552         return iprop->defaultvalue;
1553 }
1554
1555 void RNA_property_int_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1556 {
1557         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1558         
1559         if(prop->arraydimension == 0)
1560                 values[0]= iprop->defaultvalue;
1561         else if(iprop->defaultarray)
1562                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->totarraylength);
1563         else
1564                 memset(values, 0, sizeof(int)*prop->totarraylength);
1565 }
1566
1567 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1568 {
1569         int tmp[RNA_MAX_ARRAY_LENGTH];
1570         int len= rna_ensure_property_array_length(ptr, prop);
1571
1572         if(len <= RNA_MAX_ARRAY_LENGTH) {
1573                 RNA_property_int_get_default_array(ptr, prop, tmp);
1574                 return tmp[index];
1575         }
1576         else {
1577                 int *tmparray, value;
1578
1579                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_int_get_default_index");
1580                 RNA_property_int_get_default_array(ptr, prop, tmparray);
1581                 value= tmparray[index];
1582                 MEM_freeN(tmparray);
1583
1584                 return value;
1585         }
1586 }
1587
1588 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
1589 {
1590         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1591         IDProperty *idprop;
1592
1593         if((idprop=rna_idproperty_check(&prop, ptr))) {
1594                 if(idprop->type == IDP_FLOAT)
1595                         return IDP_Float(idprop);
1596                 else
1597                         return (float)IDP_Double(idprop);
1598         }
1599         else if(fprop->get)
1600                 return fprop->get(ptr);
1601         else
1602                 return fprop->defaultvalue;
1603 }
1604
1605 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
1606 {
1607         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1608         IDProperty *idprop;
1609
1610         if((idprop=rna_idproperty_check(&prop, ptr))) {
1611                 if(idprop->type == IDP_FLOAT)
1612                         IDP_Float(idprop)= value;
1613                 else
1614                         IDP_Double(idprop)= value;
1615         }
1616         else if(fprop->set) {
1617                 fprop->set(ptr, value);
1618         }
1619         else if(prop->flag & PROP_EDITABLE) {
1620                 IDPropertyTemplate val = {0};
1621                 IDProperty *group;
1622
1623                 val.f= value;
1624
1625                 group= RNA_struct_idproperties(ptr, 1);
1626                 if(group)
1627                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, val, (char*)prop->identifier));
1628         }
1629 }
1630
1631 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
1632 {
1633         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1634         IDProperty *idprop;
1635         int i;
1636
1637         if((idprop=rna_idproperty_check(&prop, ptr))) {
1638                 if(prop->arraydimension == 0)
1639                         values[0]= RNA_property_float_get(ptr, prop);
1640                 else if(idprop->subtype == IDP_FLOAT) {
1641                         memcpy(values, IDP_Array(idprop), sizeof(float)*idprop->len);
1642                 }
1643                 else {
1644                         for(i=0; i<idprop->len; i++)
1645                                 values[i]=  (float)(((double*)IDP_Array(idprop))[i]);
1646                 }
1647         }
1648         else if(prop->arraydimension == 0)
1649                 values[0]= RNA_property_float_get(ptr, prop);
1650         else if(fprop->getarray)
1651                 fprop->getarray(ptr, values);
1652         else if(fprop->defaultarray)
1653                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->totarraylength);
1654         else
1655                 memset(values, 0, sizeof(float)*prop->totarraylength);
1656 }
1657
1658 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1659 {
1660         float tmp[RNA_MAX_ARRAY_LENGTH];
1661         int len= rna_ensure_property_array_length(ptr, prop);
1662
1663         if(len <= RNA_MAX_ARRAY_LENGTH) {
1664                 RNA_property_float_get_array(ptr, prop, tmp);
1665                 return tmp[index];
1666         }
1667         else {
1668                 float *tmparray, value;
1669
1670                 tmparray= MEM_callocN(sizeof(float)*len, "RNA_property_float_get_index");
1671                 RNA_property_float_get_array(ptr, prop, tmparray);
1672                 value= tmparray[index];
1673                 MEM_freeN(tmparray);
1674
1675                 return value;
1676         }
1677
1678 }
1679
1680 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
1681 {
1682         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1683         IDProperty *idprop;
1684         int i;
1685
1686         if((idprop=rna_idproperty_check(&prop, ptr))) {
1687                 if(prop->arraydimension == 0) {
1688                         if(idprop->type == IDP_FLOAT)
1689                                 IDP_Float(idprop)= values[0];
1690                         else
1691                                 IDP_Double(idprop)= values[0];
1692                 }
1693                 else if(idprop->subtype == IDP_FLOAT) {
1694                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
1695                 }
1696                 else {
1697                         for(i=0; i<idprop->len; i++)
1698                                 ((double*)IDP_Array(idprop))[i]= values[i];
1699                 }
1700         }
1701         else if(prop->arraydimension == 0)
1702                 RNA_property_float_set(ptr, prop, values[0]);
1703         else if(fprop->setarray) {
1704                 fprop->setarray(ptr, values);
1705         }
1706         else if(prop->flag & PROP_EDITABLE) {
1707                 IDPropertyTemplate val = {0};
1708                 IDProperty *group;
1709
1710                 val.array.len= prop->totarraylength;
1711                 val.array.type= IDP_FLOAT;
1712
1713                 group= RNA_struct_idproperties(ptr, 1);
1714                 if(group) {
1715                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
1716                         IDP_AddToGroup(group, idprop);
1717                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
1718                 }
1719         }
1720 }
1721
1722 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
1723 {
1724         float tmp[RNA_MAX_ARRAY_LENGTH];
1725         int len= rna_ensure_property_array_length(ptr, prop);
1726
1727         if(len <= RNA_MAX_ARRAY_LENGTH) {
1728                 RNA_property_float_get_array(ptr, prop, tmp);
1729                 tmp[index]= value;
1730                 RNA_property_float_set_array(ptr, prop, tmp);
1731         }
1732         else {
1733                 float *tmparray;
1734
1735                 tmparray= MEM_callocN(sizeof(float)*len, "RNA_property_float_get_index");
1736                 RNA_property_float_get_array(ptr, prop, tmparray);
1737                 tmparray[index]= value;
1738                 RNA_property_float_set_array(ptr, prop, tmparray);
1739                 MEM_freeN(tmparray);
1740         }
1741 }
1742
1743 float RNA_property_float_get_default(PointerRNA *ptr, PropertyRNA *prop)
1744 {
1745         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1746         return fprop->defaultvalue;
1747 }
1748
1749 void RNA_property_float_get_default_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
1750 {
1751         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1752         
1753         if(prop->arraydimension == 0)
1754                 values[0]= fprop->defaultvalue;
1755         else if(fprop->defaultarray)
1756                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->totarraylength);
1757         else
1758                 memset(values, 0, sizeof(float)*prop->totarraylength);
1759 }
1760
1761 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1762 {
1763         float tmp[RNA_MAX_ARRAY_LENGTH];
1764         int len= rna_ensure_property_array_length(ptr, prop);
1765
1766         if(len <= RNA_MAX_ARRAY_LENGTH) {
1767                 RNA_property_float_get_default_array(ptr, prop, tmp);
1768                 return tmp[index];
1769         }
1770         else {
1771                 float *tmparray, value;
1772
1773                 tmparray= MEM_callocN(sizeof(float)*len, "RNA_property_float_get_default_index");
1774                 RNA_property_float_get_default_array(ptr, prop, tmparray);
1775                 value= tmparray[index];
1776                 MEM_freeN(tmparray);
1777
1778                 return value;
1779         }
1780 }
1781
1782 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
1783 {
1784         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1785         IDProperty *idprop;
1786
1787         if((idprop=rna_idproperty_check(&prop, ptr)))
1788                 strcpy(value, IDP_String(idprop));
1789         else if(sprop->get)
1790                 sprop->get(ptr, value);
1791         else
1792                 strcpy(value, sprop->defaultvalue);
1793 }
1794
1795 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
1796 {
1797         char *buf;
1798         int length;
1799
1800         length= RNA_property_string_length(ptr, prop);
1801
1802         if(length+1 < fixedlen)
1803                 buf= fixedbuf;
1804         else
1805                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
1806
1807         RNA_property_string_get(ptr, prop, buf);
1808
1809         return buf;
1810 }
1811
1812 /* this is the length without \0 terminator */
1813 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
1814 {
1815         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1816         IDProperty *idprop;
1817
1818         if((idprop=rna_idproperty_check(&prop, ptr)))
1819                 return strlen(IDP_String(idprop));
1820         else if(sprop->length)
1821                 return sprop->length(ptr);
1822         else
1823                 return strlen(sprop->defaultvalue);
1824 }
1825
1826 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
1827 {
1828         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1829         IDProperty *idprop;
1830
1831         if((idprop=rna_idproperty_check(&prop, ptr)))
1832                 IDP_AssignString(idprop, (char*)value);
1833         else if(sprop->set)
1834                 sprop->set(ptr, value);
1835         else if(prop->flag & PROP_EDITABLE) {
1836                 IDPropertyTemplate val = {0};
1837                 IDProperty *group;
1838
1839                 val.str= (char*)value;
1840
1841                 group= RNA_struct_idproperties(ptr, 1);
1842                 if(group)
1843                         IDP_AddToGroup(group, IDP_New(IDP_STRING, val, (char*)prop->identifier));
1844         }
1845 }
1846
1847 void RNA_property_string_get_default(PointerRNA *ptr, PropertyRNA *prop, char *value)
1848 {
1849         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1850         strcpy(value, sprop->defaultvalue);
1851 }
1852
1853 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
1854 {
1855         char *buf;
1856         int length;
1857
1858         length= RNA_property_string_default_length(ptr, prop);
1859
1860         if(length+1 < fixedlen)
1861                 buf= fixedbuf;
1862         else
1863                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
1864
1865         RNA_property_string_get_default(ptr, prop, buf);
1866
1867         return buf;
1868 }
1869
1870 /* this is the length without \0 terminator */
1871 int RNA_property_string_default_length(PointerRNA *ptr, PropertyRNA *prop)
1872 {
1873         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1874         return strlen(sprop->defaultvalue);
1875 }
1876
1877 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
1878 {
1879         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1880         IDProperty *idprop;
1881
1882         if((idprop=rna_idproperty_check(&prop, ptr)))
1883                 return IDP_Int(idprop);
1884         else if(eprop->get)
1885                 return eprop->get(ptr);
1886         else
1887                 return eprop->defaultvalue;
1888 }
1889
1890 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1891 {
1892         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1893         IDProperty *idprop;
1894
1895         if((idprop=rna_idproperty_check(&prop, ptr)))
1896                 IDP_Int(idprop)= value;
1897         else if(eprop->set) {
1898                 eprop->set(ptr, value);
1899         }
1900         else if(prop->flag & PROP_EDITABLE) {
1901                 IDPropertyTemplate val = {0};
1902                 IDProperty *group;
1903
1904                 val.i= value;
1905
1906                 group= RNA_struct_idproperties(ptr, 1);
1907                 if(group)
1908                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1909         }
1910 }
1911
1912 int RNA_property_enum_get_default(PointerRNA *ptr, PropertyRNA *prop)
1913 {
1914         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1915         return eprop->defaultvalue;
1916 }
1917
1918
1919 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
1920 {
1921         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
1922         IDProperty *idprop;
1923
1924         if((idprop=rna_idproperty_check(&prop, ptr))) {
1925                 pprop= (PointerPropertyRNA*)prop;
1926
1927                 /* for groups, data is idprop itself */
1928                 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
1929         }
1930         else if(pprop->get) {
1931                 return pprop->get(ptr);
1932         }
1933         else if(prop->flag & PROP_IDPROPERTY) {
1934                 /* XXX temporary hack to add it automatically, reading should
1935                    never do any write ops, to ensure thread safety etc .. */
1936                 RNA_property_pointer_add(ptr, prop);
1937                 return RNA_property_pointer_get(ptr, prop);
1938         }
1939         else {
1940                 PointerRNA result;
1941
1942                 memset(&result, 0, sizeof(result));
1943                 return result;
1944         }
1945 }
1946
1947 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
1948 {
1949         IDProperty *idprop;
1950
1951         if((idprop=rna_idproperty_check(&prop, ptr))) {
1952                 /* not supported */
1953         }
1954         else {
1955                 PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
1956
1957                 if(             pprop->set &&
1958                                 !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
1959                                 !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)
1960                 ) {
1961                         pprop->set(ptr, ptr_value);
1962                 }
1963         }
1964 }
1965
1966 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
1967 {
1968         IDProperty *idprop;
1969
1970         if((idprop=rna_idproperty_check(&prop, ptr))) {
1971                 /* already exists */
1972         }
1973         else if(prop->flag & PROP_IDPROPERTY) {
1974                 IDPropertyTemplate val = {0};
1975                 IDProperty *group;
1976
1977                 val.i= 0;
1978
1979                 group= RNA_struct_idproperties(ptr, 1);
1980                 if(group)
1981                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, val, (char*)prop->identifier));
1982         }
1983         else
1984                 printf("RNA_property_pointer_add %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
1985 }
1986
1987 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
1988 {
1989         IDProperty *idprop, *group;
1990
1991         if((idprop=rna_idproperty_check(&prop, ptr))) {
1992                 group= RNA_struct_idproperties(ptr, 0);
1993                 
1994                 if(group) {
1995                         IDP_RemFromGroup(group, idprop);
1996                         IDP_FreeProperty(idprop);
1997                         MEM_freeN(idprop);
1998                 }
1999         }
2000         else
2001                 printf("RNA_property_pointer_remove %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
2002 }
2003
2004 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
2005 {
2006         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
2007
2008         iter->ptr.data= rna_iterator_array_get(iter);
2009         iter->ptr.type= cprop->item_type;
2010         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
2011 }
2012
2013 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
2014 {
2015         IDProperty *idprop;
2016
2017         memset(iter, 0, sizeof(*iter));
2018
2019         if((idprop=rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
2020                 iter->parent= *ptr;
2021                 iter->prop= prop;
2022
2023                 if(idprop)
2024                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
2025                 else
2026                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
2027
2028                 if(iter->valid)
2029                         rna_property_collection_get_idp(iter);
2030
2031                 iter->idprop= 1;
2032         }
2033         else {
2034                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2035                 cprop->begin(iter, ptr);
2036         }
2037 }
2038
2039 void RNA_property_collection_next(CollectionPropertyIterator *iter)
2040 {
2041         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
2042
2043         if(iter->idprop) {
2044                 rna_iterator_array_next(iter);
2045
2046                 if(iter->valid)
2047                         rna_property_collection_get_idp(iter);
2048         }
2049         else
2050                 cprop->next(iter);
2051 }
2052
2053 void RNA_property_collection_end(CollectionPropertyIterator *iter)
2054 {
2055         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
2056
2057         if(iter->idprop)
2058                 rna_iterator_array_end(iter);
2059         else
2060                 cprop->end(iter);
2061 }
2062
2063 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
2064 {
2065         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2066         IDProperty *idprop;
2067
2068         if((idprop=rna_idproperty_check(&prop, ptr))) {
2069                 return idprop->len;
2070         }
2071         else if(cprop->length) {
2072                 return cprop->length(ptr);
2073         }
2074         else {
2075                 CollectionPropertyIterator iter;
2076                 int length= 0;
2077
2078                 RNA_property_collection_begin(ptr, prop, &iter);
2079                 for(; iter.valid; RNA_property_collection_next(&iter))
2080                         length++;
2081                 RNA_property_collection_end(&iter);
2082
2083                 return length;
2084         }
2085 }
2086
2087 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2088 {
2089         IDProperty *idprop;
2090 //      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2091
2092         if((idprop=rna_idproperty_check(&prop, ptr))) {
2093                 IDPropertyTemplate val = {0};
2094                 IDProperty *item;
2095
2096                 item= IDP_New(IDP_GROUP, val, "");
2097                 IDP_AppendArray(idprop, item);
2098                 // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory 
2099                 MEM_freeN(item);
2100         }
2101         else if(prop->flag & PROP_IDPROPERTY) {
2102                 IDProperty *group, *item;
2103                 IDPropertyTemplate val = {0};
2104
2105                 group= RNA_struct_idproperties(ptr, 1);
2106                 if(group) {
2107                         idprop= IDP_NewIDPArray(prop->identifier);
2108                         IDP_AddToGroup(group, idprop);
2109
2110                         item= IDP_New(IDP_GROUP, val, "");
2111                         IDP_AppendArray(idprop, item);
2112                         // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory
2113                         MEM_freeN(item);
2114                 }
2115         }
2116
2117         /* py api calls directly */
2118 #if 0
2119         else if(cprop->add){
2120                 if(!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2121                         ParameterList params;
2122                         RNA_parameter_list_create(&params, ptr, cprop->add);
2123                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
2124                         RNA_parameter_list_free(&params);
2125                 }
2126         }
2127         /*else
2128                 printf("RNA_property_collection_add %s.%s: not implemented for this property.\n", ptr->type->identifier, prop->identifier);*/
2129 #endif
2130
2131         if(r_ptr) {
2132                 if(idprop) {
2133                         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2134
2135                         r_ptr->data= IDP_GetIndexArray(idprop, idprop->len-1);
2136                         r_ptr->type= cprop->item_type;
2137                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
2138                 }
2139                 else
2140                         memset(r_ptr, 0, sizeof(*r_ptr));
2141         }
2142 }
2143
2144 int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
2145 {
2146         IDProperty *idprop;
2147 //      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2148
2149         if((idprop=rna_idproperty_check(&prop, ptr))) {
2150                 IDProperty tmp, *array;
2151                 int len;
2152
2153                 len= idprop->len;
2154                 array= IDP_IDPArray(idprop);
2155
2156                 if(key >= 0 && key < len) {
2157                         if(key+1 < len) {
2158                                 /* move element to be removed to the back */
2159                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
2160                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(len-(key+1)));
2161                                 memcpy(&array[len-1], &tmp, sizeof(IDProperty));
2162                         }
2163
2164                         IDP_ResizeIDPArray(idprop, len-1);
2165                 }
2166
2167                 return 1;
2168         }
2169         else if(prop->flag & PROP_IDPROPERTY)
2170                 return 1;
2171
2172         /* py api calls directly */
2173 #if 0
2174         else if(cprop->remove){
2175                 if(!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2176                         ParameterList params;
2177                         RNA_parameter_list_create(&params, ptr, cprop->remove);
2178                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
2179                         RNA_parameter_list_free(&params);
2180                 }
2181
2182                 return 0;
2183         }
2184         /*else
2185                 printf("RNA_property_collection_remove %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);*/
2186 #endif
2187         return 0;
2188 }
2189
2190 int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
2191 {
2192         IDProperty *idprop;
2193
2194         if((idprop=rna_idproperty_check(&prop, ptr))) {
2195                 IDProperty tmp, *array;
2196                 int len;
2197
2198                 len= idprop->len;
2199                 array= IDP_IDPArray(idprop);
2200
2201                 if(key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
2202                         memcpy(&tmp, &array[key], sizeof(IDProperty));
2203                         if(pos < key)
2204                                 memmove(array+pos+1, array+pos, sizeof(IDProperty)*(key - pos));
2205                         else
2206                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(pos - key));
2207                         memcpy(&array[pos], &tmp, sizeof(IDProperty));
2208                 }
2209
2210                 return 1;
2211         }
2212         else if(prop->flag & PROP_IDPROPERTY)
2213                 return 1;
2214
2215         return 0;
2216 }
2217
2218 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
2219 {
2220         IDProperty *idprop;
2221
2222         if((idprop=rna_idproperty_check(&prop, ptr)))
2223                 IDP_ResizeIDPArray(idprop, 0);
2224 }
2225
2226 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
2227 {
2228         CollectionPropertyIterator iter;
2229         int index= 0;
2230         
2231         RNA_property_collection_begin(ptr, prop, &iter);
2232         for(index=0; iter.valid; RNA_property_collection_next(&iter), index++) {
2233                 if (iter.ptr.data == t_ptr->data)
2234                         break;
2235         }
2236         RNA_property_collection_end(&iter);
2237         
2238         /* did we find it? */
2239         if (iter.valid)
2240                 return index;
2241         else
2242                 return -1;
2243 }
2244
2245 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
2246 {
2247         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2248
2249         if(cprop->lookupint) {
2250                 /* we have a callback defined, use it */
2251                 *r_ptr= cprop->lookupint(ptr, key);
2252                 return (r_ptr->data != NULL);
2253         }
2254         else {
2255                 /* no callback defined, just iterate and find the nth item */
2256                 CollectionPropertyIterator iter;
2257                 int i;
2258
2259                 RNA_property_collection_begin(ptr, prop, &iter);
2260                 for(i=0; iter.valid; RNA_property_collection_next(&iter), i++) {
2261                         if(i == key) {
2262                                 *r_ptr= iter.ptr;
2263                                 break;
2264                         }
2265                 }
2266                 RNA_property_collection_end(&iter);
2267
2268                 if(!iter.valid)
2269                         memset(r_ptr, 0, sizeof(*r_ptr));
2270
2271                 return iter.valid;
2272         }
2273 }
2274
2275 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
2276 {
2277         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2278
2279         if(cprop->lookupstring) {
2280                 /* we have a callback defined, use it */
2281                 *r_ptr= cprop->lookupstring(ptr, key);
2282                 return (r_ptr->data != NULL);
2283         }
2284         else {
2285                 /* no callback defined, compare with name properties if they exist */
2286                 CollectionPropertyIterator iter;
2287                 PropertyRNA *nameprop;
2288                 char name[256], *nameptr;
2289                 int found= 0;
2290
2291                 RNA_property_collection_begin(ptr, prop, &iter);
2292                 for(; iter.valid; RNA_property_collection_next(&iter)) {
2293                         if(iter.ptr.data && iter.ptr.type->nameproperty) {
2294                                 nameprop= iter.ptr.type->nameproperty;
2295
2296                                 nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
2297
2298                                 if(strcmp(nameptr, key) == 0) {
2299                                         *r_ptr= iter.ptr;
2300                                         found= 1;
2301                                 }
2302
2303                                 if((char *)&name != nameptr)
2304                                         MEM_freeN(nameptr);
2305
2306                                 if(found)
2307                                         break;
2308                         }
2309                 }
2310                 RNA_property_collection_end(&iter);
2311
2312                 if(!iter.valid)
2313                         memset(r_ptr, 0, sizeof(*r_ptr));
2314
2315                 return iter.valid;
2316         }
2317 }
2318
2319 int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2320 {
2321         *r_ptr= *ptr;
2322         return ((r_ptr->type = prop->srna) ? 1:0);
2323 }
2324
2325 int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
2326 {
2327         CollectionPropertyIterator iter;
2328         ArrayIterator *internal;
2329         char *arrayp;
2330
2331         if(!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
2332                 return 0;
2333
2334         RNA_property_collection_begin(ptr, prop, &iter);
2335
2336         if(iter.valid) {
2337                 /* get data from array iterator and item property */
2338                 internal= iter.internal;
2339                 arrayp= (iter.valid)? iter.ptr.data: NULL;
2340
2341                 if(internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
2342                         /* we might skip some items, so it's not a proper array */
2343                         RNA_property_collection_end(&iter);
2344                         return 0;
2345                 }
2346
2347                 array->array= arrayp + itemprop->rawoffset;
2348                 array->stride= internal->itemsize;
2349                 array->len= ((char*)internal->endptr - arrayp)/internal->itemsize;
2350                 array->type= itemprop->rawtype;
2351         }
2352         else
2353                 memset(array, 0, sizeof(RawArray));
2354
2355         RNA_property_collection_end(&iter);
2356
2357         return 1;
2358 }
2359
2360 #define RAW_GET(dtype, var, raw, a) \
2361 { \
2362         switch(raw.type) { \
2363                 case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break; \
2364                 case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break; \
2365                 case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break; \
2366                 case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break; \
2367                 case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break; \
2368                 default: var = (dtype)0; \
2369         } \
2370 }
2371
2372 #define RAW_SET(dtype, raw, a, var) \
2373 { \
2374         switch(raw.type) { \
2375                 case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break; \
2376                 case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break; \
2377                 case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break; \
2378                 case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break; \
2379                 case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break; \
2380                 default: break; \
2381         } \
2382 }
2383
2384 int RNA_raw_type_sizeof(RawPropertyType type)
2385 {
2386         switch(type) {
2387                 case PROP_RAW_CHAR: return sizeof(char);
2388                 case PROP_RAW_SHORT: return sizeof(short);
2389                 case PROP_RAW_INT: return sizeof(int);
2390                 case PROP_RAW_FLOAT: return sizeof(float);
2391                 case PROP_RAW_DOUBLE: return sizeof(double);
2392                 default: return 0;
2393         }
2394 }
2395
2396 static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
2397 {
2398         StructRNA *ptype;
2399         PointerRNA itemptr;
2400         PropertyRNA *itemprop, *iprop;
2401         PropertyType itemtype=0;
2402         RawArray in;
2403         int itemlen= 0;
2404
2405         /* initialize in array, stride assumed 0 in following code */
2406         in.array= inarray;
2407         in.type= intype;
2408         in.len= inlen;
2409         in.stride= 0;
2410
2411         ptype= RNA_property_pointer_type(ptr, prop);
2412
2413         /* try to get item property pointer */
2414         RNA_pointer_create(NULL, ptype, NULL, &itemptr);
2415         itemprop= RNA_struct_find_property(&itemptr, propname);
2416
2417         if(itemprop) {
2418                 /* we have item property pointer */
2419                 RawArray out;
2420
2421                 /* check type */
2422                 itemtype= RNA_property_type(itemprop);
2423
2424                 if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
2425                         BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
2426                         return 0;
2427                 }
2428
2429                 /* check item array */
2430                 itemlen= RNA_property_array_length(&itemptr, itemprop);
2431
2432                 /* try to access as raw array */
2433                 if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
2434                         int arraylen = (itemlen == 0) ? 1 : itemlen;
2435                         if(in.len != arraylen*out.len) {
2436                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*arraylen, in.len);
2437                                 return 0;
2438                         }
2439                         
2440                         /* matching raw types */
2441                         if(out.type == in.type) {
2442                                 void *inp= in.array;
2443                                 void *outp= out.array;
2444                                 int a, size;
2445
2446                                 size= RNA_raw_type_sizeof(out.type) * arraylen;
2447
2448                                 for(a=0; a<out.len; a++) {
2449                                         if(set) memcpy(outp, inp, size);
2450                                         else memcpy(inp, outp, size);
2451
2452                                         inp= (char*)inp + size;
2453                                         outp= (char*)outp + out.stride;
2454                                 }
2455
2456                                 return 1;
2457                         }
2458
2459                         /* could also be faster with non-matching types,
2460                          * for now we just do slower loop .. */
2461                 }
2462         }
2463
2464         {
2465                 void *tmparray= NULL;
2466                 int tmplen= 0;
2467                 int err= 0, j, a= 0;
2468                 int needconv = 1;
2469
2470                 if (((itemtype == PROP_BOOLEAN || itemtype == PROP_INT) && in.type == PROP_RAW_INT) ||
2471                         (itemtype == PROP_FLOAT && in.type == PROP_RAW_FLOAT))
2472                         /* avoid creating temporary buffer if the data type match */
2473                         needconv = 0;
2474
2475                 /* no item property pointer, can still be id property, or
2476                  * property of a type derived from the collection pointer type */
2477                 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2478                         if(itemptr.data) {
2479                                 if(itemprop) {
2480                                         /* we got the property already */
2481                                         iprop= itemprop;
2482                                 }
2483                                 else {
2484                                         /* not yet, look it up and verify if it is valid */
2485                                         iprop= RNA_struct_find_property(&itemptr, propname);
2486
2487                                         if(iprop) {
2488                                                 itemlen= RNA_property_array_length(&itemptr, iprop);
2489                                                 itemtype= RNA_property_type(iprop);
2490                                         }
2491                                         else {
2492                                                 BKE_reportf(reports, RPT_ERROR, "Property named %s not found.", propname);
2493                                                 err= 1;
2494                                                 break;
2495                                         }
2496
2497                                         if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
2498                                                 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
2499                                                 err= 1;
2500                                                 break;
2501                                         }
2502                                 }
2503
2504                                 /* editable check */
2505                                 if(RNA_property_editable(&itemptr, iprop)) {
2506                                         if(a+itemlen > in.len) {
2507                                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more).", in.len);
2508                                                 err= 1;
2509                                                 break;
2510                                         }
2511
2512                                         if(itemlen == 0) {
2513                                                 /* handle conversions */
2514                                                 if(set) {
2515                                                         switch(itemtype) {
2516                                                                 case PROP_BOOLEAN: {
2517                                                                         int b;
2518                                                                         RAW_GET(int, b, in, a);
2519                                                                         RNA_property_boolean_set(&itemptr, iprop, b);
2520                                                                         break;
2521                                                                 }
2522                                                                 case PROP_INT: {
2523                                                                         int i;
2524                                                                         RAW_GET(int, i, in, a);
2525                                                                         RNA_property_int_set(&itemptr, iprop, i);
2526                                                                         break;
2527                                                                 }
2528                                                                 case PROP_FLOAT: {
2529                                                                         float f;
2530                                                                         RAW_GET(float, f, in, a);
2531                                                                         RNA_property_float_set(&itemptr, iprop, f);
2532                                                                         break;
2533                                                                 }
2534                                                                 default:
2535                                                                         break;
2536                                                         }
2537                                                 }
2538                                                 else {
2539                                                         switch(itemtype) {
2540                                                                 case PROP_BOOLEAN: {
2541                                                                         int b= RNA_property_boolean_get(&itemptr, iprop);
2542                                                                         RAW_SET(int, in, a, b);
2543                                                                         break;
2544                                                                 }
2545                                                                 case PROP_INT: {
2546                                                                         int i= RNA_property_int_get(&itemptr, iprop);
2547                                                                         RAW_SET(int, in, a, i);
2548                                                                         break;
2549                                                                 }
2550                                                                 case PROP_FLOAT: {
2551                                                                         float f= RNA_property_float_get(&itemptr, iprop);
2552                                                                         RAW_SET(float, in, a, f);
2553                                                                         break;
2554                                                                 }
2555                                                                 default:
2556                                                                         break;
2557                                                         }
2558                                                 }
2559                                                 a++;
2560                                         }
2561                                         else if (needconv == 1) {
2562                                                 /* allocate temporary array if needed */
2563                                                 if(tmparray && tmplen != itemlen) {
2564                                                         MEM_freeN(tmparray);
2565                                                         tmparray= NULL;
2566                                                 }
2567                                                 if(!tmparray) {
2568                                                         tmparray= MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n");
2569                                                         tmplen= itemlen;
2570                                                 }
2571
2572                                                 /* handle conversions */
2573                                                 if(set) {
2574                                                         switch(itemtype) {
2575                                                                 case PROP_BOOLEAN: {
2576                                                                         for(j=0; j<itemlen; j++, a++)
2577                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
2578                                                                         RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
2579                                                                         break;
2580                                                                 }
2581                                                                 case PROP_INT: {
2582                                                                         for(j=0; j<itemlen; j++, a++)
2583                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
2584                                                                         RNA_property_int_set_array(&itemptr, iprop, tmparray);
2585                                                                         break;
2586                                                                 }
2587                                                                 case PROP_FLOAT: {
2588                                                                         for(j=0; j<itemlen; j++, a++)
2589                                                                                 RAW_GET(float, ((float*)tmparray)[j], in, a);
2590                                                                         RNA_property_float_set_array(&itemptr, iprop, tmparray);
2591                                                                         break;
2592                                                                 }
2593                                                                 default:
2594                                                                         break;
2595                                                         }
2596                                                 }
2597                                                 else {
2598                                                         switch(itemtype) {
2599                                                                 case PROP_BOOLEAN: {
2600                                                                         RNA_property_boolean_get_array(&itemptr, iprop, tmparray);
2601                                                                         for(j=0; j<itemlen; j++, a++)
2602                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
2603                                                                         break;
2604                                                                 }
2605                                                                 case PROP_INT: {
2606                                                                         RNA_property_int_get_array(&itemptr, iprop, tmparray);
2607                                                                         for(j=0; j<itemlen; j++, a++)
2608                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
2609                                                                         break;
2610                                                                 }
2611                                                                 case PROP_FLOAT: {
2612                                                                         RNA_property_float_get_array(&itemptr, iprop, tmparray);
2613                                                                         for(j=0; j<itemlen; j++, a++)
2614                                                                                 RAW_SET(float, in, a, ((float*)tmparray)[j]);
2615                                                                         break;
2616                                                                 }
2617                                                                 default:
2618                                                                         break;
2619                                                         }
2620                                                 }
2621                                         }
2622                                         else {
2623                                                 if(set) {
2624                                                         switch(itemtype) {
2625                                                                 case PROP_BOOLEAN: {
2626                                                                         RNA_property_boolean_set_array(&itemptr, iprop, &((int*)in.array)[a]);
2627                                                                         a += itemlen;
2628                                                                         break;
2629                                                                 }
2630                                                                 case PROP_INT: {
2631                                                                         RNA_property_int_set_array(&itemptr, iprop, &((int*)in.array)[a]);
2632                                                                         a += itemlen;
2633                                                                         break;
2634                                                                 }
2635                                                                 case PROP_FLOAT: {
2636                                                                         RNA_property_float_set_array(&itemptr, iprop, &((float*)in.array)[a]);
2637                                                                         a += itemlen;
2638                                                                         break;
2639                                                                 }
2640                                                                 default:
2641                                                                         break;
2642                                                         }
2643                                                 }
2644                                                 else {
2645                                                         switch(itemtype) {
2646                                                                 case PROP_BOOLEAN: {
2647                                                                         RNA_property_boolean_get_array(&itemptr, iprop, &((int*)in.array)[a]);
2648                                                                         a += itemlen;
2649                                                                         break;
2650                                                                 }
2651                                                                 case PROP_INT: {
2652                                                                         RNA_property_int_get_array(&itemptr, iprop, &((int*)in.array)[a]);
2653                                                                         a += itemlen;
2654                                                                         break;
2655                                                                 }
2656                                                                 case PROP_FLOAT: {
2657                                                                         RNA_property_float_get_array(&itemptr, iprop, &((float*)in.array)[a]);
2658                                                                         a += itemlen;
2659                                                                         break;
2660                                                                 }
2661                                                                 default:
2662                                                                         break;
2663                                                         }
2664                                                 }
2665                                         }
2666                                 }
2667                         }
2668                 }
2669                 RNA_PROP_END;
2670
2671                 if(tmparray)
2672                         MEM_freeN(tmparray);
2673
2674                 return !err;
2675         }
2676 }
2677
2678 RawPropertyType RNA_property_raw_type(PropertyRNA *prop)
2679 {
2680         if (prop->rawtype == PROP_RAW_UNSET) {
2681                 /* this property has no raw access, yet we try to provide a raw type to help building the array */
2682                 switch (prop->type) {
2683                 case PROP_BOOLEAN:
2684                         return PROP_RAW_INT;
2685                 case PROP_INT:
2686                         return PROP_RAW_INT;
2687                 case PROP_FLOAT:
2688                         return PROP_RAW_FLOAT;
2689                 case PROP_ENUM:
2690                         return PROP_RAW_INT;
2691                 default:
2692                         break;
2693                 }
2694         }
2695         return prop->rawtype;
2696 }
2697
2698 int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
2699 {
2700         return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0);
2701 }
2702
2703 int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
2704 {
2705         return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1);
2706 }
2707
2708 /* Standard iterator functions */
2709
2710 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
2711 {
2712         ListBaseIterator *internal;
2713
2714         internal= MEM_callocN(sizeof(ListBaseIterator), "ListBaseIterator");
2715         internal->link= (lb)? lb->first: NULL;
2716         internal->skip= skip;
2717
2718         iter->internal= internal;
2719         iter->valid= (internal->link != NULL);
2720
2721         if(skip && iter->valid && skip(iter, internal->link))
2722                 rna_iterator_listbase_next(iter);
2723 }
2724
2725 void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
2726 {
2727         ListBaseIterator *internal= iter->internal;
2728
2729         if(internal->skip) {
2730                 do {
2731                         internal->link= internal->link->next;
2732                         iter->valid= (internal->link != NULL);
2733                 } while(iter->valid && internal->skip(iter, internal->link));
2734         }
2735         else {
2736                 internal->link= internal->link->next;
2737                 iter->valid= (internal->link != NULL);
2738         }
2739 }
2740
2741 void *rna_iterator_listbase_get(CollectionPropertyIterator *iter)
2742 {
2743         ListBaseIterator *internal= iter->internal;
2744
2745         return internal->link;
2746 }
2747
2748 void rna_iterator_listbase_end(CollectionPropertyIterator *iter)
2749 {
2750         MEM_freeN(iter->internal);
2751         iter->internal= NULL;
2752 }
2753
2754 PointerRNA rna_listbase_lookup_int(PointerRNA *ptr, StructRNA *type, struct ListBase *lb, int index)
2755 {
2756         void *data= BLI_findlink(lb, index);
2757         return rna_pointer_inherit_refine(ptr, type, data);
2758 }
2759
2760 void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int itemsize, int length, int free_ptr, IteratorSkipFunc skip)
2761 {
2762         ArrayIterator *internal;
2763
2764         if(ptr == NULL)
2765                 length= 0;
2766
2767         internal= MEM_callocN(sizeof(ArrayIterator), "ArrayIterator");
2768         internal->ptr= ptr;
2769         internal->free_ptr= free_ptr ? ptr:NULL;
2770         internal->endptr= ((char*)ptr)+length*itemsize;
2771         internal->itemsize= itemsize;
2772         internal->skip= skip;
2773
2774         iter->internal= internal;
2775         iter->valid= (internal->ptr != internal->endptr);
2776
2777         if(skip && iter->valid && skip(iter, internal->ptr))
2778                 rna_iterator_array_next(iter);
2779 }
2780
2781 void rna_iterator_array_next(CollectionPropertyIterator *iter)
2782 {
2783         ArrayIterator *internal= iter->internal;
2784
2785         if(internal->skip) {
2786                 do {
2787                         internal->ptr += internal->itemsize;
2788                         iter->valid= (internal->ptr != internal->endptr);
2789                 } while(iter->valid && internal->skip(iter, internal->ptr));
2790         }
2791         else {
2792                 internal->ptr += internal->itemsize;
2793                 iter->valid= (internal->ptr != internal->endptr);
2794         }
2795 }
2796
2797 void *rna_iterator_array_get(CollectionPropertyIterator *iter)
2798 {
2799         ArrayIterator *internal= iter->internal;
2800
2801         return internal->ptr;
2802 }
2803
2804 void *rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
2805 {
2806         ArrayIterator *internal= iter->internal;
2807
2808         /* for ** arrays */
2809         return *(void**)(internal->ptr);
2810 }
2811
2812 void rna_iterator_array_end(CollectionPropertyIterator *iter)
2813 {
2814         ArrayIterator *internal= iter->internal;
2815         
2816         if(internal->free_ptr) {
2817                 MEM_freeN(internal->free_ptr);
2818                 internal->free_ptr= NULL;
2819         }
2820         MEM_freeN(iter->internal);
2821         iter->internal= NULL;
2822 }
2823
2824 PointerRNA rna_array_lookup_int(PointerRNA *ptr, StructRNA *type, void *data, int itemsize, int length, int index)
2825 {
2826         if(index < 0 || index >= length)
2827                 return PointerRNA_NULL;
2828
2829         return rna_pointer_inherit_refine(ptr, type, ((char*)data) + index*itemsize);
2830 }
2831
2832 /* RNA Path - Experiment */
2833
2834 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
2835 {
2836         const char *p;
2837         char *buf;
2838         int i, j, len, escape;
2839
2840         len= 0;
2841
2842         if(bracket) {
2843                 /* get data between [], check escaping ] with \] */
2844                 if(**path == '[') (*path)++;
2845                 else return NULL;
2846
2847                 p= *path;
2848
2849                 escape= 0;
2850                 while(*p && (*p != ']' || escape)) {
2851                         escape= (*p == '\\');
2852                         len++;
2853                         p++;
2854                 }
2855
2856                 if(*p != ']') return NULL;
2857         }
2858         else {
2859                 /* get data until . or [ */
2860                 p= *path;
2861
2862                 while(*p && *p != '.' && *p != '[') {
2863                         len++;
2864                         p++;
2865                 }
2866         }
2867         
2868         /* empty, return */
2869         if(len == 0)
2870                 return NULL;
2871         
2872         /* try to use fixed buffer if possible */
2873         if(len+1 < fixedlen)
2874                 buf= fixedbuf;
2875         else
2876                 buf= MEM_callocN(sizeof(char)*(len+1), "rna_path_token");
2877
2878         /* copy string, taking into account escaped ] */
2879         if(bracket) {
2880                 for(p=*path, i=0, j=0; i<len; i++, p++) {
2881                         if(*p == '\\' && *(p+1) == ']');
2882                         else buf[j++]= *p;
2883                 }
2884
2885                 buf[j]= 0;
2886         }
2887         else {
2888                 memcpy(buf, *path, sizeof(char)*len);
2889                 buf[len]= '\0';
2890         }
2891
2892         /* set path to start of next token */
2893         if(*p == ']') p++;
2894         if(*p == '.') p++;
2895         *path= p;
2896
2897         return buf;
2898 }
2899
2900 static int rna_token_strip_quotes(char *token)
2901 {
2902         if(token[0]=='"') {
2903                 int len = strlen(token);
2904                 if (len >= 2 && token[len-1]=='"') {
2905                         /* strip away "" */
2906                         token[len-1]= '\0';
2907                         return 1;
2908                 }
2909         }
2910         return 0;
2911 }
2912
2913 /* Resolve the given RNA path to find the pointer+property indicated at the end of the path */
2914 int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
2915 {
2916         return RNA_path_resolve_full(ptr, path, r_ptr, r_prop, NULL);
2917 }
2918
2919 int RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *index)
2920 {
2921         PropertyRNA *prop;
2922         PointerRNA curptr, nextptr;
2923         char fixedbuf[256], *token;
2924         int type, len, intkey;
2925
2926         prop= NULL;
2927         curptr= *ptr;
2928
2929         if(path==NULL || *path=='\0')
2930                 return 0;
2931
2932         while(*path) {
2933                 int use_id_prop = (*path=='[') ? 1:0;
2934                 /* custom property lookup ?
2935                  * C.object["someprop"]
2936                  */
2937
2938                 /* look up property name in current struct */
2939                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), use_id_prop);
2940
2941                 if(!token)
2942                         return 0;
2943
2944                 if(use_id_prop) { /* look up property name in current struct */
2945                         IDProperty *group= RNA_struct_idproperties(&curptr, 0);
2946                         if(group && rna_token_strip_quotes(token))
2947                                 prop= (PropertyRNA *)IDP_GetPropertyFromGroup(group, token+1);
2948                 }
2949                 else {
2950                         prop= RNA_struct_find_property(&curptr, token);
2951                 }
2952
2953                 if(token != fixedbuf)
2954                         MEM_freeN(token);
2955
2956                 if(!prop)
2957                         return 0;
2958
2959                 type= RNA_property_type(prop);
2960
2961                 /* now look up the value of this property if it is a pointer or
2962                  * collection, otherwise return the property rna so that the
2963                  * caller can read the value of the property itself */
2964                 switch (type) {
2965                 case PROP_POINTER:
2966                         nextptr= RNA_property_pointer_get(&curptr, prop);
2967
2968                         if(nextptr.data)
2969                                 curptr= nextptr;
2970                         else
2971                                 return 0;
2972
2973                         break;
2974                 case PROP_COLLECTION:
2975                         if(*path) {
2976                                 /* resolve the lookup with [] brackets */
2977                                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
2978
2979                                 if(!token)
2980                                         return 0;
2981
2982                                 len= strlen(token);
2983
2984                                 /* check for "" to see if it is a string */
2985                                 if(rna_token_strip_quotes(token)) {
2986                                         RNA_property_collection_lookup_string(&curptr, prop, token+1, &nextptr);
2987                                 }
2988                                 else {
2989                                         /* otherwise do int lookup */
2990                                         intkey= atoi(token);
2991                                         RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr);
2992                                 }
2993
2994                                 if(token != fixedbuf)
2995                                         MEM_freeN(token);
2996
2997                                 if(nextptr.data)
2998                                         curptr= nextptr;
2999                                 else
3000                                         return 0;
3001                         }
3002
3003                         break;
3004                 default:
3005                         if (index==NULL)
3006                                 break;
3007
3008                         *index= -1;
3009
3010                         if (*path) {
3011                                 if (*path=='[') {
3012                                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
3013
3014                                         /* check for "" to see if it is a string */
3015                                         if(rna_token_strip_quotes(token)) {
3016                                                 *index= RNA_property_array_item_index(prop, *(token+1));
3017                                         }
3018                                         else {
3019                                                 /* otherwise do int lookup */
3020                                                 *index= atoi(token);
3021                                         }
3022                                 }
3023                                 else {
3024                                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 0);
3025                                         *index= RNA_property_array_item_index(prop, *token);
3026                                 }
3027
3028                                 if(token != fixedbuf)
3029                                         MEM_freeN(token);
3030                         }
3031                 }
3032         }
3033
3034         *r_ptr= curptr;
3035         *r_prop= prop;
3036
3037         return 1;
3038 }
3039
3040
3041 char *RNA_path_append(const char *path, PointerRNA *ptr, PropertyRNA *prop, int intkey, const char *strkey)
3042 {
3043         DynStr *dynstr;
3044         const char *s;
3045         char appendstr[128], *result;
3046         
3047         dynstr= BLI_dynstr_new();
3048
3049         /* add .identifier */
3050         if(path) {
3051                 BLI_dynstr_append(dynstr, (char*)path);
3052                 if(*path)
3053                         BLI_dynstr_append(dynstr, ".");
3054         }
3055
3056         BLI_dynstr_append(dynstr, (char*)RNA_property_identifier(prop));
3057
3058         if(RNA_property_type(prop) == PROP_COLLECTION) {
3059                 /* add ["strkey"] or [intkey] */
3060                 BLI_dynstr_append(dynstr, "[");
3061
3062                 if(strkey) {
3063                         BLI_dynstr_append(dynstr, "\"");
3064                         for(s=strkey; *s; s++) {
3065                                 if(*s == '[') {
3066                                         appendstr[0]= '\\';
3067                                         appendstr[1]= *s;
3068                                         appendstr[2]= 0;
3069                                 }
3070                                 else {
3071                                         appendstr[0]= *s;
3072                                         appendstr[1]= 0;
3073                                 }
3074                                 BLI_dynstr_append(dynstr, appendstr);
3075                         }
3076                         BLI_dynstr_append(dynstr, "\"");
3077                 }
3078                 else {
3079                         sprintf(appendstr, "%d", intkey);
3080                         BLI_dynstr_append(dynstr, appendstr);
3081                 }
3082
3083                 BLI_dynstr_append(dynstr, "]");
3084         }
3085
3086         result= BLI_dynstr_get_cstring(dynstr);
3087         BLI_dynstr_free(dynstr);
3088
3089         return result;
3090 }
3091
3092 char *RNA_path_back(const char *path)
3093 {
3094         char fixedbuf[256];
3095         const char *previous, *current;
3096         char *result, *token;
3097         int i;
3098
3099         if(!path)
3100                 return NULL;
3101
3102         previous= NULL;
3103         current= path;
3104
3105         /* parse token by token until the end, then we back up to the previous
3106          * position and strip of the next token to get the path one step back */
3107         while(*current) {
3108                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 0);
3109
3110                 if(!token)
3111                         return NULL;
3112                 if(token != fixedbuf)
3113                         MEM_freeN(token);
3114
3115                 /* in case of collection we also need to strip off [] */
3116                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 1);
3117                 if(token && token != fixedbuf)
3118                         MEM_freeN(token);
3119                 
3120                 if(!*current)
3121                         break;
3122
3123                 previous= current;
3124         }
3125
3126         if(!previous)
3127                 return NULL;
3128
3129         /* copy and strip off last token */
3130         i= previous - path;
3131         result= BLI_strdup(path);
3132
3133         if(i > 0 && result[i-1] == '.') i--;
3134         result[i]= 0;
3135
3136         return result;
3137 }
3138
3139 char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
3140 {
3141         char *ptrpath=NULL;
3142
3143         if(!ptr->id.data || !ptr->data)
3144                 return NULL;
3145         
3146         if(!RNA_struct_is_ID(ptr->type)) {
3147                 if(ptr->type->path) {
3148                         /* if type has a path to some ID, use it */
3149                         ptrpath= ptr->type->path(ptr);
3150                 }
3151                 else if(ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) {
3152                         PointerRNA parentptr;
3153                         PropertyRNA *userprop;
3154                         
3155                         /* find the property in the struct we're nested in that references this struct, and 
3156                          * use its identifier as the first part of the path used...
3157                          */
3158                         RNA_id_pointer_create(ptr->id.data, &parentptr);
3159                         userprop= RNA_struct_find_nested(&parentptr, ptr->type); 
3160                         
3161                         if(userprop)
3162                                 ptrpath= BLI_strdup(RNA_property_identifier(userprop));
3163                         else
3164                                 return NULL; // can't do anything about this case yet...
3165                 }
3166                 else
3167                         return NULL;
3168         }
3169         
3170         return ptrpath;
3171 }
3172
3173 char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
3174 {
3175         int is_rna = (prop->magic == RNA_MAGIC);
3176         const char *propname;
3177         char *ptrpath, *path;
3178
3179         if(!ptr->id.data || !ptr->data || !prop)
3180                 return NULL;
3181         
3182         /* path from ID to the struct holding this property */
3183         ptrpath= RNA_path_from_ID_to_struct(ptr);
3184
3185         propname= RNA_property_identifier(prop);
3186
3187         if(ptrpath) {
3188                 path= BLI_sprintfN(is_rna ? "%s.%s":"%s[\"%s\"]", ptrpath, propname);
3189                 MEM_freeN(ptrpath);
3190         }
3191         else {
3192                 if(is_rna)
3193                         path= BLI_strdup(propname);
3194                 else
3195                         path= BLI_sprintfN("[\"%s\"]", propname);
3196         }
3197
3198         return path;
3199 }
3200
3201 /* Quick name based property access */
3202
3203 int RNA_boolean_get(PointerRNA *ptr, const char *name)
3204 {
3205         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3206
3207         if(prop) {
3208                 return RNA_property_boolean_get(ptr, prop);
3209         }
3210         else {
3211                 printf("RNA_boolean_get: %s.%s not found.\n", ptr->type->identifier, name);
3212                 return 0;
3213         }
3214 }
3215
3216 void RNA_boolean_set(PointerRNA *ptr, const char *