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