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