UI:
[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
74         r_ptr->id.data= id;
75         r_ptr->type= idtype;
76         r_ptr->data= id;
77 }
78
79 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
80 {
81         PointerRNA tmp;
82         StructRNA *idtype= NULL;
83
84         if(id) {
85                 memset(&tmp, 0, sizeof(tmp));
86                 tmp.data= id;
87                 idtype= rna_ID_refine(&tmp);
88         }
89
90         r_ptr->id.data= id;
91         r_ptr->type= type;
92         r_ptr->data= data;
93 }
94
95 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
96 {
97         if(type && type->flag & STRUCT_ID) {
98                 ptr->id.data= ptr->data;
99         }
100         else {
101                 ptr->id.data= parent->id.data;
102         }
103 }
104
105 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
106 {
107         r_ptr->id.data= NULL;
108         r_ptr->type= &RNA_BlenderRNA;
109         r_ptr->data= &BLENDER_RNA;
110 }
111
112 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
113 {
114         PointerRNA result;
115
116         if(data) {
117                 result.data= data;
118                 result.type= type;
119                 rna_pointer_inherit_id(type, ptr, &result);
120
121                 if(type->refine)
122                         result.type= type->refine(&result);
123         }
124         else
125                 memset(&result, 0, sizeof(result));
126         
127         return result;
128 }
129
130 /* ID Properties */
131
132 IDProperty *rna_idproperties_get(PointerRNA *ptr, int create)
133 {
134         if(ptr->type->flag & STRUCT_ID)
135                 return IDP_GetProperties(ptr->data, create);
136         else if(ptr->type == &RNA_IDPropertyGroup || ptr->type->base == &RNA_IDPropertyGroup)
137                 return ptr->data;
138         else if(ptr->type->base == &RNA_OperatorProperties) {
139                 if(create && !ptr->data) {
140                         IDPropertyTemplate val;
141                         val.i = 0; /* silence MSVC warning about uninitialized var when debugging */
142                         ptr->data= IDP_New(IDP_GROUP, val, "RNA_OperatorProperties group");
143                 }
144
145                 return ptr->data;
146         }
147         else
148                 return NULL;
149 }
150
151 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
152 {
153         IDProperty *group= rna_idproperties_get(ptr, 0);
154         IDProperty *idprop;
155
156         if(group) {
157                 for(idprop=group->data.group.first; idprop; idprop=idprop->next)
158                         if(strcmp(idprop->name, name) == 0)
159                                 return idprop;
160         }
161         
162         return NULL;
163 }
164
165 static int rna_idproperty_verify_valid(PropertyRNA *prop, IDProperty *idprop)
166 {
167         /* this verifies if the idproperty actually matches the property
168          * description and otherwise removes it. this is to ensure that
169          * rna property access is type safe, e.g. if you defined the rna
170          * to have a certain array length you can count on that staying so */
171         
172         switch(idprop->type) {
173                 case IDP_IDPARRAY:
174                         if(prop->type != PROP_COLLECTION)
175                                 return 0;
176                         break;
177                 case IDP_ARRAY:
178                         if(prop->arraylength != idprop->len)
179                                 return 0;
180
181                         if(idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
182                                 return 0;
183                         if(idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
184                                 return 0;
185
186                         break;
187                 case IDP_INT:
188                         if(!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
189                                 return 0;
190                         break;
191                 case IDP_FLOAT:
192                 case IDP_DOUBLE:
193                         if(prop->type != PROP_FLOAT)
194                                 return 0;
195                         break;
196                 case IDP_STRING:
197                         if(prop->type != PROP_STRING)
198                                 return 0;
199                         break;
200                 case IDP_GROUP:
201                         if(prop->type != PROP_POINTER)
202                                 return 0;
203                         break;
204                 default:
205                         return 0;
206         }
207
208         return 1;
209 }
210
211 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
212 {
213         /* This is quite a hack, but avoids some complexity in the API. we
214          * pass IDProperty structs as PropertyRNA pointers to the outside.
215          * We store some bytes in PropertyRNA structs that allows us to
216          * distinguish it from IDProperty structs. If it is an ID property,
217          * we look up an IDP PropertyRNA based on the type, and set the data
218          * pointer to the IDProperty. */
219
220         if((*prop)->magic == RNA_MAGIC) {
221                 if((*prop)->flag & PROP_IDPROPERTY) {
222                         IDProperty *idprop= rna_idproperty_find(ptr, (*prop)->identifier);
223
224                         if(idprop && !rna_idproperty_verify_valid(*prop, idprop)) {
225                                 IDProperty *group= rna_idproperties_get(ptr, 0);
226
227                                 IDP_RemFromGroup(group, idprop);
228                                 IDP_FreeProperty(idprop);
229                                 MEM_freeN(idprop);
230                                 return NULL;
231                         }
232
233                         return idprop;
234                 }
235                 else
236                         return NULL;
237         }
238
239         {
240                 static PropertyRNA *typemap[IDP_NUMTYPES] =
241                         {(PropertyRNA*)&rna_IDProperty_string,
242                          (PropertyRNA*)&rna_IDProperty_int,
243                          (PropertyRNA*)&rna_IDProperty_float,
244                          NULL, NULL, NULL,
245                          (PropertyRNA*)&rna_IDProperty_group, NULL,
246                          (PropertyRNA*)&rna_IDProperty_double};
247
248                 static PropertyRNA *arraytypemap[IDP_NUMTYPES] =
249                         {NULL, (PropertyRNA*)&rna_IDProperty_int_array,
250                          (PropertyRNA*)&rna_IDProperty_float_array,
251                          NULL, NULL, NULL,
252                          (PropertyRNA*)&rna_IDProperty_collection, NULL,
253                          (PropertyRNA*)&rna_IDProperty_double_array};
254
255                 IDProperty *idprop= (IDProperty*)(*prop);
256
257                 if(idprop->type == IDP_ARRAY)
258                         *prop= arraytypemap[(int)(idprop->subtype)];
259                 else 
260                         *prop= typemap[(int)(idprop->type)];
261
262                 return idprop;
263         }
264 }
265
266 /* Structs */
267
268 const char *RNA_struct_identifier(PointerRNA *ptr)
269 {
270         return ptr->type->identifier;
271 }
272
273 const char *RNA_struct_ui_name(PointerRNA *ptr)
274 {
275         return ptr->type->name;
276 }
277
278 const char *RNA_struct_ui_description(PointerRNA *ptr)
279 {
280         return ptr->type->description;
281 }
282
283 PropertyRNA *RNA_struct_name_property(PointerRNA *ptr)
284 {
285         return ptr->type->nameproperty;
286 }
287
288 PropertyRNA *RNA_struct_iterator_property(PointerRNA *ptr)
289 {
290         return ptr->type->iteratorproperty;
291 }
292
293 int RNA_struct_is_ID(PointerRNA *ptr)
294 {
295         return (ptr->type->flag & STRUCT_ID) != 0;
296 }
297
298 int RNA_struct_is_a(PointerRNA *ptr, StructRNA *srna)
299 {
300         StructRNA *type;
301
302         /* ptr->type is always maximally refined */
303         for(type=ptr->type; type; type=type->base)
304                 if(type == srna)
305                         return 1;
306         
307         return 0;
308 }
309
310 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
311 {
312         CollectionPropertyIterator iter;
313         PropertyRNA *iterprop, *prop;
314         int i = 0;
315
316         iterprop= RNA_struct_iterator_property(ptr);
317         RNA_property_collection_begin(ptr, iterprop, &iter);
318         prop= NULL;
319
320         for(; iter.valid; RNA_property_collection_next(&iter), i++) {
321                 if(strcmp(identifier, RNA_property_identifier(ptr, iter.ptr.data)) == 0) {
322                         prop= iter.ptr.data;
323                         break;
324                 }
325         }
326
327         RNA_property_collection_end(&iter);
328
329         return prop;
330 }
331
332 const struct ListBase *RNA_struct_defined_properties(StructRNA *srna)
333 {
334         return &srna->properties;
335 }
336
337 /* Property Information */
338
339 const char *RNA_property_identifier(PointerRNA *ptr, PropertyRNA *prop)
340 {
341         IDProperty *idprop;
342
343         if((idprop=rna_idproperty_check(&prop, ptr)))
344                 return idprop->name;
345         else
346                 return prop->identifier;
347 }
348
349 PropertyType RNA_property_type(PointerRNA *ptr, PropertyRNA *prop)
350 {
351         rna_idproperty_check(&prop, ptr);
352
353         return prop->type;
354 }
355
356 PropertySubType RNA_property_subtype(PointerRNA *ptr, PropertyRNA *prop)
357 {
358         rna_idproperty_check(&prop, ptr);
359
360         return prop->subtype;
361 }
362
363 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
364 {
365         IDProperty *idprop;
366
367         if((idprop=rna_idproperty_check(&prop, ptr)) && idprop->type==IDP_ARRAY)
368                 return idprop->len;
369         else
370                 return prop->arraylength;
371 }
372
373 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
374 {
375         IntPropertyRNA *iprop;
376         
377         rna_idproperty_check(&prop, ptr);
378         iprop= (IntPropertyRNA*)prop;
379
380         if(iprop->range) {
381                 iprop->range(ptr, hardmin, hardmax);
382         }
383         else {
384                 *hardmin= iprop->hardmin;
385                 *hardmax= iprop->hardmax;
386         }
387 }
388
389 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
390 {
391         IntPropertyRNA *iprop;
392         int hardmin, hardmax;
393         
394         rna_idproperty_check(&prop, ptr);
395         iprop= (IntPropertyRNA*)prop;
396
397         if(iprop->range) {
398                 iprop->range(ptr, &hardmin, &hardmax);
399                 *softmin= MAX2(iprop->softmin, hardmin);
400                 *softmax= MIN2(iprop->softmax, hardmax);
401         }
402         else {
403                 *softmin= iprop->softmin;
404                 *softmax= iprop->softmax;
405         }
406
407         *step= iprop->step;
408 }
409
410 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
411 {
412         FloatPropertyRNA *fprop;
413
414         rna_idproperty_check(&prop, ptr);
415         fprop= (FloatPropertyRNA*)prop;
416
417         if(fprop->range) {
418                 fprop->range(ptr, hardmin, hardmax);
419         }
420         else {
421                 *hardmin= fprop->hardmin;
422                 *hardmax= fprop->hardmax;
423         }
424 }
425
426 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
427 {
428         FloatPropertyRNA *fprop;
429         float hardmin, hardmax;
430
431         rna_idproperty_check(&prop, ptr);
432         fprop= (FloatPropertyRNA*)prop;
433
434         if(fprop->range) {
435                 fprop->range(ptr, &hardmin, &hardmax);
436                 *softmin= MAX2(fprop->softmin, hardmin);
437                 *softmax= MIN2(fprop->softmax, hardmax);
438         }
439         else {
440                 *softmin= fprop->softmin;
441                 *softmax= fprop->softmax;
442         }
443
444         *step= fprop->step;
445         *precision= (float)fprop->precision;
446 }
447
448 int RNA_property_string_maxlength(PointerRNA *ptr, PropertyRNA *prop)
449 {
450         StringPropertyRNA *sprop;
451         
452         rna_idproperty_check(&prop, ptr);
453         sprop= (StringPropertyRNA*)prop;
454
455         return sprop->maxlength;
456 }
457
458 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
459 {
460         rna_idproperty_check(&prop, ptr);
461
462         if(prop->type == PROP_POINTER) {
463                 PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
464
465                 if(pprop->type)
466                         return pprop->type;
467         }
468         else if(prop->type == PROP_COLLECTION) {
469                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
470
471                 if(cprop->type)
472                         return cprop->type;
473         }
474
475         return &RNA_UnknownType;
476 }
477
478 void RNA_property_enum_items(PointerRNA *ptr, PropertyRNA *prop, const EnumPropertyItem **item, int *totitem)
479 {
480         EnumPropertyRNA *eprop;
481
482         rna_idproperty_check(&prop, ptr);
483         eprop= (EnumPropertyRNA*)prop;
484
485         *item= eprop->item;
486         *totitem= eprop->totitem;
487 }
488
489 int RNA_property_enum_value(PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
490 {       
491         const EnumPropertyItem *item;
492         int totitem, i;
493         
494         RNA_property_enum_items(ptr, prop, &item, &totitem);
495         
496         for (i=0; i<totitem; i++) {
497                 if (strcmp(item[i].identifier, identifier)==0) {
498                         *value = item[i].value;
499                         return 1;
500                 }
501         }
502
503         return 0;
504 }
505
506 int RNA_property_enum_identifier(PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
507 {       
508         const EnumPropertyItem *item;
509         int totitem, i;
510         
511         RNA_property_enum_items(ptr, prop, &item, &totitem);
512         
513         for (i=0; i<totitem; i++) {
514                 if (item[i].value==value) {
515                         *identifier = item[i].identifier;
516                         return 1;
517                 }
518         }
519         
520         return 0;
521 }
522
523 const char *RNA_property_ui_name(PointerRNA *ptr, PropertyRNA *prop)
524 {
525         PropertyRNA *oldprop= prop;
526         IDProperty *idprop;
527
528         if((idprop=rna_idproperty_check(&prop, ptr)) && oldprop!=prop)
529                 return idprop->name;
530         else
531                 return prop->name;
532 }
533
534 const char *RNA_property_ui_description(PointerRNA *ptr, PropertyRNA *prop)
535 {
536         PropertyRNA *oldprop= prop;
537
538         if(rna_idproperty_check(&prop, ptr) && oldprop!=prop)
539                 return "";
540         else
541                 return prop->description;
542 }
543
544 int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
545 {
546         int flag;
547
548         rna_idproperty_check(&prop, ptr);
549
550         if(prop->editable)
551                 flag= prop->editable(ptr);
552         else
553                 flag= prop->flag;
554
555         return (flag & PROP_EDITABLE);
556 }
557
558 int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
559 {
560         int flag;
561
562         rna_idproperty_check(&prop, ptr);
563
564         if(!(prop->flag & PROP_ANIMATEABLE))
565                 return 0;
566
567         if(prop->editable)
568                 flag= prop->editable(ptr);
569         else
570                 flag= prop->flag;
571
572         return (flag & PROP_EDITABLE);
573 }
574
575 int RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
576 {
577         /* would need to ask animation system */
578
579         return 0;
580 }
581
582 void RNA_property_update(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop)
583 {
584         rna_idproperty_check(&prop, ptr);
585
586         if(prop->update)
587                 prop->update(C, ptr);
588         if(prop->noteflag)
589                 WM_event_add_notifier(C, prop->noteflag, ptr->id.data);
590 }
591
592 /* Property Data */
593
594 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
595 {
596         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
597         IDProperty *idprop;
598
599         if((idprop=rna_idproperty_check(&prop, ptr)))
600                 return IDP_Int(idprop);
601         else if(bprop->get)
602                 return bprop->get(ptr);
603         else
604                 return bprop->defaultvalue;
605 }
606
607 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
608 {
609         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
610         IDProperty *idprop;
611
612         if((idprop=rna_idproperty_check(&prop, ptr)))
613                 IDP_Int(idprop)= value;
614         else if(bprop->set)
615                 bprop->set(ptr, value);
616         else if(prop->flag & PROP_EDITABLE) {
617                 IDPropertyTemplate val;
618                 IDProperty *group;
619
620                 val.i= value;
621
622                 group= rna_idproperties_get(ptr, 1);
623                 if(group)
624                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
625         }
626 }
627
628 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
629 {
630         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
631         IDProperty *idprop;
632
633         if((idprop=rna_idproperty_check(&prop, ptr))) {
634                 if(prop->arraylength == 0)
635                         values[0]= RNA_property_boolean_get(ptr, prop);
636                 else
637                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
638         }
639         else if(prop->arraylength == 0)
640                 values[0]= RNA_property_boolean_get(ptr, prop);
641         else if(bprop->getarray)
642                 bprop->getarray(ptr, values);
643         else if(bprop->defaultarray)
644                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->arraylength);
645         else
646                 memset(values, 0, sizeof(int)*prop->arraylength);
647 }
648
649 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
650 {
651         int tmp[RNA_MAX_ARRAY];
652
653         RNA_property_boolean_get_array(ptr, prop, tmp);
654         return tmp[index];
655 }
656
657 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
658 {
659         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
660         IDProperty *idprop;
661
662         if((idprop=rna_idproperty_check(&prop, ptr))) {
663                 if(prop->arraylength == 0)
664                         IDP_Int(idprop)= values[0];
665                 else
666                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
667         }
668         else if(prop->arraylength == 0)
669                 RNA_property_boolean_set(ptr, prop, values[0]);
670         else if(bprop->setarray)
671                 bprop->setarray(ptr, values);
672         else if(prop->flag & PROP_EDITABLE) {
673                 IDPropertyTemplate val;
674                 IDProperty *group;
675
676                 val.array.len= prop->arraylength;
677                 val.array.type= IDP_INT;
678
679                 group= rna_idproperties_get(ptr, 1);
680                 if(group) {
681                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
682                         IDP_AddToGroup(group, idprop);
683                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
684                 }
685         }
686 }
687
688 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
689 {
690         int tmp[RNA_MAX_ARRAY];
691
692         RNA_property_boolean_get_array(ptr, prop, tmp);
693         tmp[index]= value;
694         RNA_property_boolean_set_array(ptr, prop, tmp);
695 }
696
697 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
698 {
699         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
700         IDProperty *idprop;
701
702         if((idprop=rna_idproperty_check(&prop, ptr)))
703                 return IDP_Int(idprop);
704         else if(iprop->get)
705                 return iprop->get(ptr);
706         else
707                 return iprop->defaultvalue;
708 }
709
710 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
711 {
712         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
713         IDProperty *idprop;
714
715         if((idprop=rna_idproperty_check(&prop, ptr)))
716                 IDP_Int(idprop)= value;
717         else if(iprop->set)
718                 iprop->set(ptr, value);
719         else if(prop->flag & PROP_EDITABLE) {
720                 IDPropertyTemplate val;
721                 IDProperty *group;
722
723                 val.i= value;
724
725                 group= rna_idproperties_get(ptr, 1);
726                 if(group)
727                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
728         }
729 }
730
731 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
732 {
733         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
734         IDProperty *idprop;
735
736         if((idprop=rna_idproperty_check(&prop, ptr))) {
737                 if(prop->arraylength == 0)
738                         values[0]= RNA_property_int_get(ptr, prop);
739                 else
740                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
741         }
742         else if(prop->arraylength == 0)
743                 values[0]= RNA_property_int_get(ptr, prop);
744         else if(iprop->getarray)
745                 iprop->getarray(ptr, values);
746         else if(iprop->defaultarray)
747                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->arraylength);
748         else
749                 memset(values, 0, sizeof(int)*prop->arraylength);
750 }
751
752 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
753 {
754         int tmp[RNA_MAX_ARRAY];
755
756         RNA_property_int_get_array(ptr, prop, tmp);
757         return tmp[index];
758 }
759
760 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
761 {
762         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
763         IDProperty *idprop;
764
765         if((idprop=rna_idproperty_check(&prop, ptr))) {
766                 if(prop->arraylength == 0)
767                         IDP_Int(idprop)= values[0];
768                 else
769                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);\
770         }
771         else if(prop->arraylength == 0)
772                 RNA_property_int_set(ptr, prop, values[0]);
773         else if(iprop->setarray)
774                 iprop->setarray(ptr, values);
775         else if(prop->flag & PROP_EDITABLE) {
776                 IDPropertyTemplate val;
777                 IDProperty *group;
778
779                 val.array.len= prop->arraylength;
780                 val.array.type= IDP_INT;
781
782                 group= rna_idproperties_get(ptr, 1);
783                 if(group) {
784                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
785                         IDP_AddToGroup(group, idprop);
786                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
787                 }
788         }
789 }
790
791 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
792 {
793         int tmp[RNA_MAX_ARRAY];
794
795         RNA_property_int_get_array(ptr, prop, tmp);
796         tmp[index]= value;
797         RNA_property_int_set_array(ptr, prop, tmp);
798 }
799
800 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
801 {
802         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
803         IDProperty *idprop;
804
805         if((idprop=rna_idproperty_check(&prop, ptr))) {
806                 if(idprop->type == IDP_FLOAT)
807                         return IDP_Float(idprop);
808                 else
809                         return (float)IDP_Double(idprop);
810         }
811         else if(fprop->get)
812                 return fprop->get(ptr);
813         else
814                 return fprop->defaultvalue;
815 }
816
817 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
818 {
819         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
820         IDProperty *idprop;
821
822         if((idprop=rna_idproperty_check(&prop, ptr))) {
823                 if(idprop->type == IDP_FLOAT)
824                         IDP_Float(idprop)= value;
825                 else
826                         IDP_Double(idprop)= value;
827         }
828         else if(fprop->set) {
829                 fprop->set(ptr, value);
830         }
831         else if(prop->flag & PROP_EDITABLE) {
832                 IDPropertyTemplate val;
833                 IDProperty *group;
834
835                 val.f= value;
836
837                 group= rna_idproperties_get(ptr, 1);
838                 if(group)
839                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, val, (char*)prop->identifier));
840         }
841 }
842
843 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
844 {
845         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
846         IDProperty *idprop;
847         int i;
848
849         if((idprop=rna_idproperty_check(&prop, ptr))) {
850                 if(prop->arraylength == 0)
851                         values[0]= RNA_property_float_get(ptr, prop);
852                 else if(idprop->subtype == IDP_FLOAT) {
853                         memcpy(values, IDP_Array(idprop), sizeof(float)*idprop->len);
854                 }
855                 else {
856                         for(i=0; i<idprop->len; i++)
857                                 values[i]=  (float)(((double*)IDP_Array(idprop))[i]);
858                 }
859         }
860         else if(prop->arraylength == 0)
861                 values[0]= RNA_property_float_get(ptr, prop);
862         else if(fprop->getarray)
863                 fprop->getarray(ptr, values);
864         else if(fprop->defaultarray)
865                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->arraylength);
866         else
867                 memset(values, 0, sizeof(float)*prop->arraylength);
868 }
869
870 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
871 {
872         float tmp[RNA_MAX_ARRAY];
873
874         RNA_property_float_get_array(ptr, prop, tmp);
875         return tmp[index];
876 }
877
878 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
879 {
880         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
881         IDProperty *idprop;
882         int i;
883
884         if((idprop=rna_idproperty_check(&prop, ptr))) {
885                 if(prop->arraylength == 0)
886                         IDP_Double(idprop)= values[0];
887                 else if(idprop->subtype == IDP_FLOAT) {
888                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
889                 }
890                 else {
891                         for(i=0; i<idprop->len; i++)
892                                 ((double*)IDP_Array(idprop))[i]= values[i];
893                 }
894         }
895         else if(prop->arraylength == 0)
896                 RNA_property_float_set(ptr, prop, values[0]);
897         else if(fprop->setarray) {
898                 fprop->setarray(ptr, values);
899         }
900         else if(prop->flag & PROP_EDITABLE) {
901                 IDPropertyTemplate val;
902                 IDProperty *group;
903
904                 val.array.len= prop->arraylength;
905                 val.array.type= IDP_FLOAT;
906
907                 group= rna_idproperties_get(ptr, 1);
908                 if(group) {
909                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
910                         IDP_AddToGroup(group, idprop);
911                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
912                 }
913         }
914 }
915
916 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
917 {
918         float tmp[RNA_MAX_ARRAY];
919
920         RNA_property_float_get_array(ptr, prop, tmp);
921         tmp[index]= value;
922         RNA_property_float_set_array(ptr, prop, tmp);
923 }
924
925 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
926 {
927         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
928         IDProperty *idprop;
929
930         if((idprop=rna_idproperty_check(&prop, ptr)))
931                 strcpy(value, IDP_String(idprop));
932         else if(sprop->get)
933                 sprop->get(ptr, value);
934         else
935                 strcpy(value, sprop->defaultvalue);
936 }
937
938 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
939 {
940         char *buf;
941         int length;
942
943         length= RNA_property_string_length(ptr, prop);
944
945         if(length+1 < fixedlen)
946                 buf= fixedbuf;
947         else
948                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
949
950         RNA_property_string_get(ptr, prop, buf);
951
952         return buf;
953 }
954
955 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
956 {
957         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
958         IDProperty *idprop;
959
960         if((idprop=rna_idproperty_check(&prop, ptr)))
961                 return strlen(IDP_String(idprop));
962         else if(sprop->length)
963                 return sprop->length(ptr);
964         else
965                 return strlen(sprop->defaultvalue);
966 }
967
968 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
969 {
970         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
971         IDProperty *idprop;
972
973         if((idprop=rna_idproperty_check(&prop, ptr)))
974                 IDP_AssignString(idprop, (char*)value);
975         else if(sprop->set)
976                 sprop->set(ptr, value);
977         else if(prop->flag & PROP_EDITABLE) {
978                 IDPropertyTemplate val;
979                 IDProperty *group;
980
981                 val.str= (char*)value;
982
983                 group= rna_idproperties_get(ptr, 1);
984                 if(group)
985                         IDP_AddToGroup(group, IDP_New(IDP_STRING, val, (char*)prop->identifier));
986         }
987 }
988
989 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
990 {
991         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
992         IDProperty *idprop;
993
994         if((idprop=rna_idproperty_check(&prop, ptr)))
995                 return IDP_Int(idprop);
996         else if(eprop->get)
997                 return eprop->get(ptr);
998         else
999                 return eprop->defaultvalue;
1000 }
1001
1002
1003 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1004 {
1005         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1006         IDProperty *idprop;
1007
1008         if((idprop=rna_idproperty_check(&prop, ptr)))
1009                 IDP_Int(idprop)= value;
1010         else if(eprop->set) {
1011                 eprop->set(ptr, value);
1012         }
1013         else if(prop->flag & PROP_EDITABLE) {
1014                 IDPropertyTemplate val;
1015                 IDProperty *group;
1016
1017                 val.i= value;
1018
1019                 group= rna_idproperties_get(ptr, 1);
1020                 if(group)
1021                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1022         }
1023 }
1024
1025 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
1026 {
1027         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
1028         IDProperty *idprop;
1029
1030         if((idprop=rna_idproperty_check(&prop, ptr))) {
1031                 pprop= (PointerPropertyRNA*)prop;
1032
1033                 /* for groups, data is idprop itself */
1034                 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
1035         }
1036         else if(pprop->get) {
1037                 return pprop->get(ptr);
1038         }
1039         else {
1040                 PointerRNA result;
1041                 memset(&result, 0, sizeof(result));
1042                 return result;
1043         }
1044 }
1045
1046 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
1047 {
1048         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
1049
1050         if(pprop->set)
1051                 pprop->set(ptr, ptr_value);
1052 }
1053
1054 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
1055 {
1056         IDProperty *idprop;
1057
1058         if((idprop=rna_idproperty_check(&prop, ptr))) {
1059                 /* already exists */
1060         }
1061         else if(prop->flag & PROP_IDPROPERTY) {
1062                 IDPropertyTemplate val;
1063                 IDProperty *group;
1064
1065                 val.i= 0;
1066
1067                 group= rna_idproperties_get(ptr, 1);
1068                 if(group)
1069                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, val, (char*)prop->identifier));
1070         }
1071         else
1072                 printf("RNA_property_pointer_add %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
1073 }
1074
1075 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
1076 {
1077         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1078
1079         iter->ptr.data= rna_iterator_array_get(iter);
1080         iter->ptr.type= cprop->type;
1081         rna_pointer_inherit_id(cprop->type, &iter->parent, &iter->ptr);
1082 }
1083
1084 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
1085 {
1086         IDProperty *idprop;
1087
1088         memset(iter, 0, sizeof(*iter));
1089
1090         if((idprop=rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
1091                 iter->parent= *ptr;
1092                 iter->prop= prop;
1093
1094                 if(idprop)
1095                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, NULL);
1096                 else
1097                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, NULL);
1098
1099                 if(iter->valid)
1100                         rna_property_collection_get_idp(iter);
1101
1102                 iter->idprop= 1;
1103         }
1104         else {
1105                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1106                 cprop->begin(iter, ptr);
1107         }
1108 }
1109
1110 void RNA_property_collection_next(CollectionPropertyIterator *iter)
1111 {
1112         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1113
1114         if(iter->idprop) {
1115                 rna_iterator_array_next(iter);
1116
1117                 if(iter->valid)
1118                         rna_property_collection_get_idp(iter);
1119         }
1120         else
1121                 cprop->next(iter);
1122 }
1123
1124 void RNA_property_collection_end(CollectionPropertyIterator *iter)
1125 {
1126         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1127
1128         if(iter->idprop)
1129                 rna_iterator_array_end(iter);
1130         else
1131                 cprop->end(iter);
1132 }
1133
1134 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
1135 {
1136         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1137         IDProperty *idprop;
1138
1139         if((idprop=rna_idproperty_check(&prop, ptr))) {
1140                 return idprop->len;
1141         }
1142         else if(cprop->length) {
1143                 return cprop->length(ptr);
1144         }
1145         else {
1146                 CollectionPropertyIterator iter;
1147                 int length= 0;
1148
1149                 RNA_property_collection_begin(ptr, prop, &iter);
1150                 for(; iter.valid; RNA_property_collection_next(&iter))
1151                         length++;
1152                 RNA_property_collection_end(&iter);
1153
1154                 return length;
1155         }
1156 }
1157
1158 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
1159 {
1160         IDProperty *idprop;
1161
1162         if((idprop=rna_idproperty_check(&prop, ptr))) {
1163                 IDPropertyTemplate val;
1164                 IDProperty *item;
1165                 val.i= 0;
1166
1167                 item= IDP_New(IDP_GROUP, val, "");
1168                 IDP_AppendArray(idprop, item);
1169                 IDP_FreeProperty(item);
1170                 MEM_freeN(item);
1171         }
1172         else if(prop->flag & PROP_IDPROPERTY) {
1173                 IDProperty *group, *item;
1174                 IDPropertyTemplate val;
1175                 val.i= 0;
1176
1177                 group= rna_idproperties_get(ptr, 1);
1178                 if(group) {
1179                         idprop= IDP_NewIDPArray(prop->identifier);
1180                         IDP_AddToGroup(group, idprop);
1181
1182                         item= IDP_New(IDP_GROUP, val, "");
1183                         IDP_AppendArray(idprop, item);
1184                         IDP_FreeProperty(item);
1185                         MEM_freeN(item);
1186                 }
1187         }
1188         else
1189                 printf("RNA_property_collection_add %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
1190
1191         if(r_ptr) {
1192                 if(idprop) {
1193                         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1194
1195                         r_ptr->data= IDP_GetIndexArray(idprop, idprop->len-1);
1196                         r_ptr->type= cprop->type;
1197                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
1198                 }
1199                 else
1200                         memset(r_ptr, 0, sizeof(*r_ptr));
1201         }
1202 }
1203
1204 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
1205 {
1206         IDProperty *idprop;
1207
1208         if((idprop=rna_idproperty_check(&prop, ptr)))
1209                 IDP_ResizeIDPArray(idprop, 0);
1210 }
1211
1212 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
1213 {
1214         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1215
1216         if(cprop->lookupint) {
1217                 /* we have a callback defined, use it */
1218                 *r_ptr= cprop->lookupint(ptr, key);
1219                 return (r_ptr->data != NULL);
1220         }
1221         else {
1222                 /* no callback defined, just iterate and find the nth item */
1223                 CollectionPropertyIterator iter;
1224                 int i;
1225
1226                 RNA_property_collection_begin(ptr, prop, &iter);
1227                 for(i=0; iter.valid; RNA_property_collection_next(&iter), i++) {
1228                         if(i == key) {
1229                                 *r_ptr= iter.ptr;
1230                                 break;
1231                         }
1232                 }
1233                 RNA_property_collection_end(&iter);
1234
1235                 if(!iter.valid)
1236                         memset(r_ptr, 0, sizeof(*r_ptr));
1237
1238                 return iter.valid;
1239         }
1240 }
1241
1242 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
1243 {
1244         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1245
1246         if(cprop->lookupstring) {
1247                 /* we have a callback defined, use it */
1248                 *r_ptr= cprop->lookupstring(ptr, key);
1249                 return (r_ptr->data != NULL);
1250         }
1251         else {
1252                 /* no callback defined, compare with name properties if they exist */
1253                 CollectionPropertyIterator iter;
1254                 PropertyRNA *nameprop;
1255                 char name[256], *nameptr;
1256                 int found= 0;
1257
1258                 RNA_property_collection_begin(ptr, prop, &iter);
1259                 for(; iter.valid; RNA_property_collection_next(&iter)) {
1260                         if(iter.ptr.data && iter.ptr.type->nameproperty) {
1261                                 nameprop= iter.ptr.type->nameproperty;
1262
1263                                 nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
1264
1265                                 if(strcmp(nameptr, key) == 0) {
1266                                         *r_ptr= iter.ptr;
1267                                         found= 1;
1268                                 }
1269
1270                                 if ((char *)&name != nameptr)
1271                                         MEM_freeN(nameptr);
1272
1273                                 if(found)
1274                                         break;
1275                         }
1276                 }
1277                 RNA_property_collection_end(&iter);
1278
1279                 if(!iter.valid)
1280                         memset(r_ptr, 0, sizeof(*r_ptr));
1281
1282                 return iter.valid;
1283         }
1284 }
1285
1286 /* Standard iterator functions */
1287
1288 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
1289 {
1290         ListBaseIterator *internal;
1291
1292         internal= MEM_callocN(sizeof(ListBaseIterator), "ListBaseIterator");
1293         internal->link= lb->first;
1294         internal->skip= skip;
1295
1296         iter->internal= internal;
1297         iter->valid= (internal->link != NULL);
1298
1299         if(skip && iter->valid && skip(iter, internal->link))
1300                 rna_iterator_listbase_next(iter);
1301 }
1302
1303 void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
1304 {
1305         ListBaseIterator *internal= iter->internal;
1306
1307         if(internal->skip) {
1308                 do {
1309                         internal->link= internal->link->next;
1310                         iter->valid= (internal->link != NULL);
1311                 } while(iter->valid && internal->skip(iter, internal->link));
1312         }
1313         else {
1314                 internal->link= internal->link->next;
1315                 iter->valid= (internal->link != NULL);
1316         }
1317 }
1318
1319 void *rna_iterator_listbase_get(CollectionPropertyIterator *iter)
1320 {
1321         ListBaseIterator *internal= iter->internal;
1322
1323         return internal->link;
1324 }
1325
1326 void rna_iterator_listbase_end(CollectionPropertyIterator *iter)
1327 {
1328         MEM_freeN(iter->internal);
1329 }
1330
1331 void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int itemsize, int length, IteratorSkipFunc skip)
1332 {
1333         ArrayIterator *internal;
1334
1335         if(ptr == NULL)
1336                 length= 0;
1337
1338         internal= MEM_callocN(sizeof(ArrayIterator), "ArrayIterator");
1339         internal->ptr= ptr;
1340         internal->endptr= ((char*)ptr)+length*itemsize;
1341         internal->itemsize= itemsize;
1342         internal->skip= skip;
1343
1344         iter->internal= internal;
1345         iter->valid= (internal->ptr != internal->endptr);
1346
1347         if(skip && iter->valid && skip(iter, internal->ptr))
1348                 rna_iterator_array_next(iter);
1349 }
1350
1351 void rna_iterator_array_next(CollectionPropertyIterator *iter)
1352 {
1353         ArrayIterator *internal= iter->internal;
1354
1355         if(internal->skip) {
1356                 do {
1357                         internal->ptr += internal->itemsize;
1358                         iter->valid= (internal->ptr != internal->endptr);
1359                 } while(iter->valid && internal->skip(iter, internal->ptr));
1360         }
1361         else {
1362                 internal->ptr += internal->itemsize;
1363                 iter->valid= (internal->ptr != internal->endptr);
1364         }
1365 }
1366
1367 void *rna_iterator_array_get(CollectionPropertyIterator *iter)
1368 {
1369         ArrayIterator *internal= iter->internal;
1370
1371         return internal->ptr;
1372 }
1373
1374 void *rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
1375 {
1376         ArrayIterator *internal= iter->internal;
1377
1378         /* for ** arrays */
1379         return *(void**)(internal->ptr);
1380 }
1381
1382 void rna_iterator_array_end(CollectionPropertyIterator *iter)
1383 {
1384         MEM_freeN(iter->internal);
1385 }
1386
1387 /* RNA Path - Experiment */
1388
1389 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
1390 {
1391         const char *p;
1392         char *buf;
1393         int i, j, len, escape;
1394
1395         len= 0;
1396
1397         if(bracket) {
1398                 /* get data between [], check escaping ] with \] */
1399                 if(**path == '[') (*path)++;
1400                 else return NULL;
1401
1402                 p= *path;
1403
1404                 escape= 0;
1405                 while(*p && (*p != ']' || escape)) {
1406                         escape= (*p == '\\');
1407                         len++;
1408                         p++;
1409                 }
1410
1411                 if(*p != ']') return NULL;
1412         }
1413         else {
1414                 /* get data until . or [ */
1415                 p= *path;
1416
1417                 while(*p && *p != '.' && *p != '[') {
1418                         len++;
1419                         p++;
1420                 }
1421         }
1422         
1423         /* empty, return */
1424         if(len == 0)
1425                 return NULL;
1426         
1427         /* try to use fixed buffer if possible */
1428         if(len+1 < fixedlen)
1429                 buf= fixedbuf;
1430         else
1431                 buf= MEM_callocN(sizeof(char)*(len+1), "rna_path_token");
1432
1433         /* copy string, taking into account escaped ] */
1434         for(p=*path, i=0, j=0; i<len; i++, p++) {
1435                 if(*p == '\\' && *(p+1) == ']');
1436                 else buf[j++]= *p;
1437         }
1438
1439         buf[j]= 0;
1440
1441         /* set path to start of next token */
1442         if(*p == ']') p++;
1443         if(*p == '.') p++;
1444         *path= p;
1445
1446         return buf;
1447 }
1448
1449 int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
1450 {
1451         CollectionPropertyIterator iter;
1452         PropertyRNA *prop, *iterprop;
1453         PointerRNA curptr, nextptr;
1454         char fixedbuf[256], *token;
1455         int len, intkey;
1456
1457         prop= NULL;
1458         curptr= *ptr;
1459
1460         while(*path) {
1461                 /* look up property name in current struct */
1462                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 0);
1463
1464                 if(!token)
1465                         return 0;
1466
1467                 iterprop= RNA_struct_iterator_property(&curptr);
1468                 RNA_property_collection_begin(&curptr, iterprop, &iter);
1469                 prop= NULL;
1470
1471                 for(; iter.valid; RNA_property_collection_next(&iter)) {
1472                         if(strcmp(token, RNA_property_identifier(&curptr, iter.ptr.data)) == 0) {
1473                                 prop= iter.ptr.data;
1474                                 break;
1475                         }
1476                 }
1477
1478                 RNA_property_collection_end(&iter);
1479
1480                 if(token != fixedbuf)
1481                         MEM_freeN(token);
1482
1483                 if(!prop)
1484                         return 0;
1485
1486                 /* now look up the value of this property if it is a pointer or
1487                  * collection, otherwise return the property rna so that the
1488                  * caller can read the value of the property itself */
1489                 if(RNA_property_type(&curptr, prop) == PROP_POINTER) {
1490                         nextptr= RNA_property_pointer_get(&curptr, prop);
1491
1492                         if(nextptr.data)
1493                                 curptr= nextptr;
1494                         else
1495                                 return 0;
1496                 }
1497                 else if(RNA_property_type(&curptr, prop) == PROP_COLLECTION && *path) {
1498                         /* resolve the lookup with [] brackets */
1499                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
1500
1501                         if(!token)
1502                                 return 0;
1503
1504                         len= strlen(token);
1505                         
1506                         /* check for "" to see if it is a string */
1507                         if(len >= 2 && token[0] == '"' && token[len-1] == '"') {
1508                                 /* strip away "" */
1509                                 token[len-1]= 0;
1510                                 RNA_property_collection_lookup_string(&curptr, prop, token+1, &nextptr);
1511                         }
1512                         else {
1513                                 /* otherwise do int lookup */
1514                                 intkey= atoi(token);
1515                                 RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr);
1516                         }
1517
1518                         if(token != fixedbuf)
1519                                 MEM_freeN(token);
1520
1521                         if(nextptr.data)
1522                                 curptr= nextptr;
1523                         else
1524                                 return 0;
1525                 }
1526         }
1527
1528         *r_ptr= curptr;
1529         *r_prop= prop;
1530
1531         return 1;
1532 }
1533
1534 char *RNA_path_append(const char *path, PointerRNA *ptr, PropertyRNA *prop, int intkey, const char *strkey)
1535 {
1536         DynStr *dynstr;
1537         const char *s;
1538         char appendstr[128], *result;
1539         
1540         dynstr= BLI_dynstr_new();
1541
1542         /* add .identifier */
1543         if(path) {
1544                 BLI_dynstr_append(dynstr, (char*)path);
1545                 if(*path)
1546                         BLI_dynstr_append(dynstr, ".");
1547         }
1548
1549         BLI_dynstr_append(dynstr, (char*)RNA_property_identifier(ptr, prop));
1550
1551         if(RNA_property_type(ptr, prop) == PROP_COLLECTION) {
1552                 /* add ["strkey"] or [intkey] */
1553                 BLI_dynstr_append(dynstr, "[");
1554
1555                 if(strkey) {
1556                         BLI_dynstr_append(dynstr, "\"");
1557                         for(s=strkey; *s; s++) {
1558                                 if(*s == '[') {
1559                                         appendstr[0]= '\\';
1560                                         appendstr[1]= *s;
1561                                         appendstr[2]= 0;
1562                                 }
1563                                 else {
1564                                         appendstr[0]= *s;
1565                                         appendstr[1]= 0;
1566                                 }
1567                                 BLI_dynstr_append(dynstr, appendstr);
1568                         }
1569                         BLI_dynstr_append(dynstr, "\"");
1570                 }
1571                 else {
1572                         sprintf(appendstr, "%d", intkey);
1573                         BLI_dynstr_append(dynstr, appendstr);
1574                 }
1575
1576                 BLI_dynstr_append(dynstr, "]");
1577         }
1578
1579         result= BLI_dynstr_get_cstring(dynstr);
1580         BLI_dynstr_free(dynstr);
1581
1582         return result;
1583 }
1584
1585 char *RNA_path_back(const char *path)
1586 {
1587         char fixedbuf[256];
1588         const char *previous, *current;
1589         char *result, *token;
1590         int i;
1591
1592         if(!path)
1593                 return NULL;
1594
1595         previous= NULL;
1596         current= path;
1597
1598         /* parse token by token until the end, then we back up to the previous
1599          * position and strip of the next token to get the path one step back */
1600         while(*current) {
1601                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 0);
1602
1603                 if(!token)
1604                         return NULL;
1605                 if(token != fixedbuf)
1606                         MEM_freeN(token);
1607
1608                 /* in case of collection we also need to strip off [] */
1609                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 1);
1610                 if(token && token != fixedbuf)
1611                         MEM_freeN(token);
1612                 
1613                 if(!*current)
1614                         break;
1615
1616                 previous= current;
1617         }
1618
1619         if(!previous)
1620                 return NULL;
1621
1622         /* copy and strip off last token */
1623         i= previous - path;
1624         result= BLI_strdup(path);
1625
1626         if(i > 0 && result[i-1] == '.') i--;
1627         result[i]= 0;
1628
1629         return result;
1630 }
1631
1632 char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
1633 {
1634         char *ptrpath=NULL, *path;
1635         const char *propname;
1636
1637         if(!ptr->id.data || !ptr->data || !prop)
1638                 return NULL;
1639         
1640         if(!RNA_struct_is_ID(ptr)) {
1641                 if(ptr->type->path)
1642                         ptrpath= ptr->type->path(ptr);
1643                 else
1644                         return NULL;
1645         }
1646
1647         propname= RNA_property_identifier(ptr, prop);
1648
1649         if(ptrpath) {
1650                 path= BLI_sprintfN("%s.%s", ptrpath, propname);
1651                 MEM_freeN(ptrpath);
1652         }
1653         else
1654                 path= BLI_strdup(propname);
1655         
1656         return path;
1657 }
1658
1659 /* Quick name based property access */
1660
1661 int RNA_boolean_get(PointerRNA *ptr, const char *name)
1662 {
1663         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1664
1665         if(prop) {
1666                 return RNA_property_boolean_get(ptr, prop);
1667         }
1668         else {
1669                 printf("RNA_boolean_get: %s.%s not found.\n", ptr->type->identifier, name);
1670                 return 0;
1671         }
1672 }
1673
1674 void RNA_boolean_set(PointerRNA *ptr, const char *name, int value)
1675 {
1676         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1677
1678         if(prop)
1679                 RNA_property_boolean_set(ptr, prop, value);
1680         else
1681                 printf("RNA_boolean_set: %s.%s not found.\n", ptr->type->identifier, name);
1682 }
1683
1684 void RNA_boolean_get_array(PointerRNA *ptr, const char *name, int *values)
1685 {
1686         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1687
1688         if(prop)
1689                 RNA_property_boolean_get_array(ptr, prop, values);
1690         else
1691                 printf("RNA_boolean_get_array: %s.%s not found.\n", ptr->type->identifier, name);
1692 }
1693
1694 void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const int *values)
1695 {
1696         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1697
1698         if(prop)
1699                 RNA_property_boolean_set_array(ptr, prop, values);
1700         else
1701                 printf("RNA_boolean_set_array: %s.%s not found.\n", ptr->type->identifier, name);
1702 }
1703
1704 int RNA_int_get(PointerRNA *ptr, const char *name)
1705 {
1706         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1707
1708         if(prop) {
1709                 return RNA_property_int_get(ptr, prop);
1710         }
1711         else {
1712                 printf("RNA_int_get: %s.%s not found.\n", ptr->type->identifier, name);
1713                 return 0;
1714         }
1715 }
1716
1717 void RNA_int_set(PointerRNA *ptr, const char *name, int value)
1718 {
1719         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1720
1721         if(prop)
1722                 RNA_property_int_set(ptr, prop, value);
1723         else
1724                 printf("RNA_int_set: %s.%s not found.\n", ptr->type->identifier, name);
1725 }
1726
1727 void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
1728 {
1729         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1730
1731         if(prop)
1732                 RNA_property_int_get_array(ptr, prop, values);
1733         else
1734                 printf("RNA_int_get_array: %s.%s not found.\n", ptr->type->identifier, name);
1735 }
1736
1737 void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
1738 {
1739         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1740
1741         if(prop)
1742                 RNA_property_int_set_array(ptr, prop, values);
1743         else
1744                 printf("RNA_int_set_array: %s.%s not found.\n", ptr->type->identifier, name);
1745 }
1746
1747 float RNA_float_get(PointerRNA *ptr, const char *name)
1748 {
1749         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1750
1751         if(prop) {
1752                 return RNA_property_float_get(ptr, prop);
1753         }
1754         else {
1755                 printf("RNA_float_get: %s.%s not found.\n", ptr->type->identifier, name);
1756                 return 0;
1757         }
1758 }
1759
1760 void RNA_float_set(PointerRNA *ptr, const char *name, float value)
1761 {
1762         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1763
1764         if(prop)
1765                 RNA_property_float_set(ptr, prop, value);
1766         else
1767                 printf("RNA_float_set: %s.%s not found.\n", ptr->type->identifier, name);
1768 }
1769
1770 void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
1771 {
1772         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1773
1774         if(prop)
1775                 RNA_property_float_get_array(ptr, prop, values);
1776         else
1777                 printf("RNA_float_get_array: %s.%s not found.\n", ptr->type->identifier, name);
1778 }
1779
1780 void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
1781 {
1782         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1783
1784         if(prop)
1785                 RNA_property_float_set_array(ptr, prop, values);
1786         else
1787                 printf("RNA_float_set_array: %s.%s not found.\n", ptr->type->identifier, name);
1788 }
1789
1790 int RNA_enum_get(PointerRNA *ptr, const char *name)
1791 {
1792         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1793
1794         if(prop) {
1795                 return RNA_property_enum_get(ptr, prop);
1796         }
1797         else {
1798                 printf("RNA_enum_get: %s.%s not found.\n", ptr->type->identifier, name);
1799                 return 0;
1800         }
1801 }
1802
1803 void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
1804 {
1805         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1806
1807         if(prop)
1808                 RNA_property_enum_set(ptr, prop, value);
1809         else
1810                 printf("RNA_enum_set: %s.%s not found.\n", ptr->type->identifier, name);
1811 }
1812
1813 int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname)
1814 {
1815         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1816         const EnumPropertyItem *item;
1817         int a, totitem;
1818
1819         if(prop) {
1820                 RNA_property_enum_items(ptr, prop, &item, &totitem);
1821
1822                 for(a=0; a<totitem; a++)
1823                         if(strcmp(item[a].identifier, enumname) == 0)
1824                                 return (item[a].value == RNA_property_enum_get(ptr, prop));
1825
1826                 printf("RNA_enum_is_equal: %s.%s item %s not found.\n", ptr->type->identifier, name, enumname);
1827                 return 0;
1828         }
1829         else {
1830                 printf("RNA_enum_is_equal: %s.%s not found.\n", ptr->type->identifier, name);
1831                 return 0;
1832         }
1833 }
1834
1835 void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
1836 {
1837         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1838
1839         if(prop)
1840                 RNA_property_string_get(ptr, prop, value);
1841         else
1842                 printf("RNA_string_get: %s.%s not found.\n", ptr->type->identifier, name);
1843 }
1844
1845 char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen)
1846 {
1847         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1848
1849         if(prop) {
1850                 return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen);
1851         }
1852         else {
1853                 printf("RNA_string_get_alloc: %s.%s not found.\n", ptr->type->identifier, name);
1854                 return 0;
1855         }
1856 }
1857
1858 int RNA_string_length(PointerRNA *ptr, const char *name)
1859 {
1860         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1861
1862         if(prop) {
1863                 return RNA_property_string_length(ptr, prop);
1864         }
1865         else {
1866                 printf("RNA_string_length: %s.%s not found.\n", ptr->type->identifier, name);
1867                 return 0;
1868         }
1869 }
1870
1871 void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
1872 {
1873         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1874
1875         if(prop)
1876                 RNA_property_string_set(ptr, prop, value);
1877         else
1878                 printf("RNA_string_set: %s.%s not found.\n", ptr->type->identifier, name);
1879 }
1880
1881 PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
1882 {
1883         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1884
1885         if(prop) {
1886                 return RNA_property_pointer_get(ptr, prop);
1887         }
1888         else {
1889                 PointerRNA result;
1890
1891                 printf("RNA_pointer_get: %s.%s not found.\n", ptr->type->identifier, name);
1892
1893                 memset(&result, 0, sizeof(result));
1894                 return result;
1895         }
1896 }
1897
1898 void RNA_pointer_add(PointerRNA *ptr, const char *name)
1899 {
1900         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1901
1902         if(prop)
1903                 RNA_property_pointer_add(ptr, prop);
1904         else
1905                 printf("RNA_pointer_set: %s.%s not found.\n", ptr->type->identifier, name);
1906 }
1907
1908 void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter)
1909 {
1910         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1911
1912         if(prop)
1913                 RNA_property_collection_begin(ptr, prop, iter);
1914         else
1915                 printf("RNA_collection_begin: %s.%s not found.\n", ptr->type->identifier, name);
1916 }
1917
1918 void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
1919 {
1920         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1921
1922         if(prop)
1923                 RNA_property_collection_add(ptr, prop, r_value);
1924         else
1925                 printf("RNA_collection_add: %s.%s not found.\n", ptr->type->identifier, name);
1926 }
1927
1928 void RNA_collection_clear(PointerRNA *ptr, const char *name)
1929 {
1930         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1931
1932         if(prop)
1933                 RNA_property_collection_clear(ptr, prop);
1934         else
1935                 printf("RNA_collection_clear: %s.%s not found.\n", ptr->type->identifier, name);
1936 }
1937
1938 int RNA_collection_length(PointerRNA *ptr, const char *name)
1939 {
1940         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1941
1942         if(prop) {
1943                 return RNA_property_collection_length(ptr, prop);
1944         }
1945         else {
1946                 printf("RNA_collection_length: %s.%s not found.\n", ptr->type->identifier, name);
1947                 return 0;
1948         }
1949 }
1950
1951 int RNA_property_is_set(PointerRNA *ptr, const char *name)
1952 {
1953         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1954
1955         if(prop) {
1956                 return (rna_idproperty_find(ptr, name) != NULL);
1957         }
1958         else {
1959                 printf("RNA_property_is_set: %s.%s not found.\n", ptr->type->identifier, name);
1960                 return 0;
1961         }
1962 }
1963
1964 /* string representation of a property, python
1965  * compatible but can be used for display too*/
1966 char *RNA_property_as_string(PointerRNA *ptr, PropertyRNA *prop)
1967 {
1968         int type = RNA_property_type(ptr, prop);
1969         int len = RNA_property_array_length(ptr, prop);
1970         int i;
1971
1972         DynStr *dynstr= BLI_dynstr_new();
1973         char *cstring;
1974         
1975
1976         /* see if we can coorce into a python type - PropertyType */
1977         switch (type) {
1978         case PROP_BOOLEAN:
1979                 if (len==0) {
1980                         BLI_dynstr_append(dynstr, RNA_property_boolean_get(ptr, prop) ? "True" : "False");
1981                 }
1982                 else {
1983                         BLI_dynstr_append(dynstr, "(");
1984                         for(i=0; i<len; i++) {
1985                                 BLI_dynstr_appendf(dynstr, i?", %s":"%s", RNA_property_boolean_get_index(ptr, prop, i) ? "True" : "False");
1986                         }
1987                         BLI_dynstr_append(dynstr, ")");
1988                 }
1989                 break;
1990         case PROP_INT:
1991                 if (len==0) {
1992                         BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get(ptr, prop));
1993                 }
1994                 else {
1995                         BLI_dynstr_append(dynstr, "(");
1996                         for(i=0; i<len; i++) {
1997                                 BLI_dynstr_appendf(dynstr, i?", %d":"%d", RNA_property_int_get_index(ptr, prop, i));
1998                         }
1999                         BLI_dynstr_append(dynstr, ")");
2000                 }
2001                 break;
2002         case PROP_FLOAT:
2003                 if (len==0) {
2004                         BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get(ptr, prop));
2005                 }
2006                 else {
2007                         BLI_dynstr_append(dynstr, "(");
2008                         for(i=0; i<len; i++) {
2009                                 BLI_dynstr_appendf(dynstr, i?", %g":"%g", RNA_property_float_get_index(ptr, prop, i));
2010                         }
2011                         BLI_dynstr_append(dynstr, ")");
2012                 }
2013                 break;
2014         case PROP_STRING:
2015         {
2016                 /* string arrays dont exist */
2017                 char *buf;
2018                 buf = RNA_property_string_get_alloc(ptr, prop, NULL, -1);
2019                 BLI_dynstr_appendf(dynstr, "\"%s\"", buf);
2020                 MEM_freeN(buf);
2021                 break;
2022         }
2023         case PROP_ENUM:
2024         {
2025                 /* string arrays dont exist */
2026                 const char *identifier;
2027                 int val = RNA_property_enum_get(ptr, prop);
2028
2029                 if (RNA_property_enum_identifier(ptr, prop, val, &identifier)) {
2030                         BLI_dynstr_appendf(dynstr, "'%s'", identifier);
2031                 }
2032                 else {
2033                         BLI_dynstr_appendf(dynstr, "'<UNKNOWN ENUM>'", identifier);
2034                 }
2035                 break;
2036         }
2037         case PROP_POINTER:
2038         {
2039                 BLI_dynstr_append(dynstr, "'<POINTER>'"); /* TODO */
2040                 break;
2041         }
2042         case PROP_COLLECTION:
2043                 BLI_dynstr_append(dynstr, "'<COLLECTION>'"); /* TODO */
2044                 break;
2045         default:
2046                 BLI_dynstr_append(dynstr, "'<UNKNOWN TYPE>'"); /* TODO */
2047                 break;
2048         }
2049
2050         cstring = BLI_dynstr_get_cstring(dynstr);
2051         BLI_dynstr_free(dynstr);
2052         return cstring;
2053 }
2054