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