RNA: C API
[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 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
585 {
586         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
587         IDProperty *idprop;
588
589         if((idprop=rna_idproperty_check(&prop, ptr)))
590                 memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
591         else if(bprop->getarray)
592                 bprop->getarray(ptr, values);
593         else if(bprop->defaultarray)
594                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->arraylength);
595         else
596                 memset(values, 0, sizeof(int)*prop->arraylength);
597 }
598
599 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
600 {
601         int tmp[RNA_MAX_ARRAY];
602
603         RNA_property_boolean_get_array(ptr, prop, tmp);
604         return tmp[index];
605 }
606
607 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
608 {
609         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
610         IDProperty *idprop;
611
612         if((idprop=rna_idproperty_check(&prop, ptr)))
613                 memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
614         else if(bprop->setarray)
615                 bprop->setarray(ptr, values);
616         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
617                 IDPropertyTemplate val;
618                 IDProperty *group;
619
620                 val.array.len= prop->arraylength;
621                 val.array.type= IDP_INT;
622
623                 group= rna_idproperties_get(ptr, 1);
624                 if(group) {
625                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
626                         IDP_AddToGroup(group, idprop);
627                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
628                 }
629         }
630 }
631
632 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
633 {
634         int tmp[RNA_MAX_ARRAY];
635
636         RNA_property_boolean_get_array(ptr, prop, tmp);
637         tmp[index]= value;
638         RNA_property_boolean_set_array(ptr, prop, tmp);
639 }
640
641 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
642 {
643         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
644         IDProperty *idprop;
645
646         if((idprop=rna_idproperty_check(&prop, ptr)))
647                 return IDP_Int(idprop);
648         else if(iprop->get)
649                 return iprop->get(ptr);
650         else
651                 return iprop->defaultvalue;
652 }
653
654 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
655 {
656         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
657         IDProperty *idprop;
658
659         if((idprop=rna_idproperty_check(&prop, ptr)))
660                 IDP_Int(idprop)= value;
661         else if(iprop->set)
662                 iprop->set(ptr, value);
663         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
664                 IDPropertyTemplate val;
665                 IDProperty *group;
666
667                 val.i= value;
668
669                 group= rna_idproperties_get(ptr, 1);
670                 if(group)
671                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
672         }
673 }
674
675 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
676 {
677         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
678         IDProperty *idprop;
679
680         if((idprop=rna_idproperty_check(&prop, ptr)))
681                 memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
682         else if(iprop->getarray)
683                 iprop->getarray(ptr, values);
684         else if(iprop->defaultarray)
685                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->arraylength);
686         else
687                 memset(values, 0, sizeof(int)*prop->arraylength);
688 }
689
690 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
691 {
692         int tmp[RNA_MAX_ARRAY];
693
694         RNA_property_int_get_array(ptr, prop, tmp);
695         return tmp[index];
696 }
697
698 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
699 {
700         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
701         IDProperty *idprop;
702
703         if((idprop=rna_idproperty_check(&prop, ptr)))
704                 memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
705         else if(iprop->setarray)
706                 iprop->setarray(ptr, values);
707         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
708                 IDPropertyTemplate val;
709                 IDProperty *group;
710
711                 val.array.len= prop->arraylength;
712                 val.array.type= IDP_INT;
713
714                 group= rna_idproperties_get(ptr, 1);
715                 if(group) {
716                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
717                         IDP_AddToGroup(group, idprop);
718                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
719                 }
720         }
721 }
722
723 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
724 {
725         int tmp[RNA_MAX_ARRAY];
726
727         RNA_property_int_get_array(ptr, prop, tmp);
728         tmp[index]= value;
729         RNA_property_int_set_array(ptr, prop, tmp);
730 }
731
732 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
733 {
734         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
735         IDProperty *idprop;
736
737         if((idprop=rna_idproperty_check(&prop, ptr))) {
738                 if(idprop->type == IDP_FLOAT)
739                         return IDP_Float(idprop);
740                 else
741                         return (float)IDP_Double(idprop);
742         }
743         else if(fprop->get)
744                 return fprop->get(ptr);
745         else
746                 return fprop->defaultvalue;
747 }
748
749 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
750 {
751         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
752         IDProperty *idprop;
753
754         if((idprop=rna_idproperty_check(&prop, ptr))) {
755                 if(idprop->type == IDP_FLOAT)
756                         IDP_Float(idprop)= value;
757                 else
758                         IDP_Double(idprop)= value;
759         }
760         else if(fprop->set) {
761                 fprop->set(ptr, value);
762         }
763         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
764                 IDPropertyTemplate val;
765                 IDProperty *group;
766
767                 val.f= value;
768
769                 group= rna_idproperties_get(ptr, 1);
770                 if(group)
771                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, val, (char*)prop->identifier));
772         }
773 }
774
775 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
776 {
777         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
778         IDProperty *idprop;
779         int i;
780
781         if((idprop=rna_idproperty_check(&prop, ptr))) {
782                 if(idprop->subtype == IDP_FLOAT) {
783                         memcpy(values, IDP_Array(idprop), sizeof(float)*idprop->len);
784                 }
785                 else {
786                         for(i=0; i<idprop->len; i++)
787                                 values[i]=  (float)(((double*)IDP_Array(idprop))[i]);
788                 }
789         }
790         else if(fprop->getarray)
791                 fprop->getarray(ptr, values);
792         else if(fprop->defaultarray)
793                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->arraylength);
794         else
795                 memset(values, 0, sizeof(float)*prop->arraylength);
796
797 }
798
799 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
800 {
801         float tmp[RNA_MAX_ARRAY];
802
803         RNA_property_float_get_array(ptr, prop, tmp);
804         return tmp[index];
805 }
806
807 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
808 {
809         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
810         IDProperty *idprop;
811         int i;
812
813         if((idprop=rna_idproperty_check(&prop, ptr))) {
814                 if(idprop->subtype == IDP_FLOAT) {
815                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
816                 }
817                 else {
818                         for(i=0; i<idprop->len; i++)
819                                 ((double*)IDP_Array(idprop))[i]= values[i];
820                 }
821         }
822         else if(fprop->setarray) {
823                 fprop->setarray(ptr, values);
824         }
825         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
826                 IDPropertyTemplate val;
827                 IDProperty *group;
828
829                 val.array.len= prop->arraylength;
830                 val.array.type= IDP_FLOAT;
831
832                 group= rna_idproperties_get(ptr, 1);
833                 if(group) {
834                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
835                         IDP_AddToGroup(group, idprop);
836                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
837                 }
838         }
839 }
840
841 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
842 {
843         float tmp[RNA_MAX_ARRAY];
844
845         RNA_property_float_get_array(ptr, prop, tmp);
846         tmp[index]= value;
847         RNA_property_float_set_array(ptr, prop, tmp);
848 }
849
850 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
851 {
852         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
853         IDProperty *idprop;
854
855         if((idprop=rna_idproperty_check(&prop, ptr)))
856                 strcpy(value, IDP_String(idprop));
857         else if(sprop->get)
858                 sprop->get(ptr, value);
859         else
860                 strcpy(value, sprop->defaultvalue);
861 }
862
863 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
864 {
865         char *buf;
866         int length;
867
868         length= RNA_property_string_length(ptr, prop);
869
870         if(length+1 < fixedlen)
871                 buf= fixedbuf;
872         else
873                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
874
875         RNA_property_string_get(ptr, prop, buf);
876
877         return buf;
878 }
879
880 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
881 {
882         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
883         IDProperty *idprop;
884
885         if((idprop=rna_idproperty_check(&prop, ptr)))
886                 return strlen(IDP_String(idprop));
887         else if(sprop->length)
888                 return sprop->length(ptr);
889         else
890                 return strlen(sprop->defaultvalue);
891 }
892
893 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
894 {
895         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
896         IDProperty *idprop;
897
898         if((idprop=rna_idproperty_check(&prop, ptr)))
899                 IDP_AssignString(idprop, (char*)value);
900         else if(sprop->set)
901                 sprop->set(ptr, value);
902         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
903                 IDPropertyTemplate val;
904                 IDProperty *group;
905
906                 val.str= (char*)value;
907
908                 group= rna_idproperties_get(ptr, 1);
909                 if(group)
910                         IDP_AddToGroup(group, IDP_New(IDP_STRING, val, (char*)prop->identifier));
911         }
912 }
913
914 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
915 {
916         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
917         IDProperty *idprop;
918
919         if((idprop=rna_idproperty_check(&prop, ptr)))
920                 return IDP_Int(idprop);
921         else if(eprop->get)
922                 return eprop->get(ptr);
923         else
924                 return eprop->defaultvalue;
925 }
926
927
928 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
929 {
930         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
931         IDProperty *idprop;
932
933         if((idprop=rna_idproperty_check(&prop, ptr)))
934                 IDP_Int(idprop)= value;
935         else if(eprop->set) {
936                 eprop->set(ptr, value);
937         }
938         else if(!(prop->flag & PROP_NOT_EDITABLE)) {
939                 IDPropertyTemplate val;
940                 IDProperty *group;
941
942                 val.i= value;
943
944                 group= rna_idproperties_get(ptr, 1);
945                 if(group)
946                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
947         }
948 }
949
950 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
951 {
952         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
953         IDProperty *idprop;
954
955         if((idprop=rna_idproperty_check(&prop, ptr))) {
956                 pprop= (PointerPropertyRNA*)prop;
957
958                 /* for groups, data is idprop itself */
959                 return rna_pointer_inherit_refine(ptr, pprop->structtype, idprop);
960         }
961         else if(pprop->get) {
962                 return pprop->get(ptr);
963         }
964         else {
965                 PointerRNA result;
966                 memset(&result, 0, sizeof(result));
967                 return result;
968         }
969 }
970
971 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
972 {
973         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
974
975         if(pprop->set)
976                 pprop->set(ptr, ptr_value);
977 }
978
979 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
980 {
981         IDProperty *idprop;
982
983         if((idprop=rna_idproperty_check(&prop, ptr))) {
984                 /* already exists */
985         }
986         else if(prop->flag & PROP_IDPROPERTY) {
987                 IDPropertyTemplate val;
988                 IDProperty *group;
989
990                 val.i= 0;
991
992                 group= rna_idproperties_get(ptr, 1);
993                 if(group)
994                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, val, (char*)prop->identifier));
995         }
996         else
997                 printf("RNA_property_pointer_add %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
998 }
999
1000 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
1001 {
1002         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1003
1004         iter->ptr.data= rna_iterator_array_get(iter);
1005         iter->ptr.type= cprop->structtype;
1006         rna_pointer_inherit_id(cprop->structtype, &iter->parent, &iter->ptr);
1007 }
1008
1009 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
1010 {
1011         IDProperty *idprop;
1012
1013         memset(iter, 0, sizeof(*iter));
1014
1015         if((idprop=rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
1016                 iter->parent= *ptr;
1017                 iter->prop= prop;
1018
1019                 if(idprop)
1020                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, NULL);
1021                 else
1022                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, NULL);
1023
1024                 if(iter->valid)
1025                         rna_property_collection_get_idp(iter);
1026
1027                 iter->idprop= 1;
1028         }
1029         else {
1030                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1031                 cprop->begin(iter, ptr);
1032         }
1033 }
1034
1035 void RNA_property_collection_next(CollectionPropertyIterator *iter)
1036 {
1037         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1038
1039         if(iter->idprop) {
1040                 rna_iterator_array_next(iter);
1041
1042                 if(iter->valid)
1043                         rna_property_collection_get_idp(iter);
1044         }
1045         else
1046                 cprop->next(iter);
1047 }
1048
1049 void RNA_property_collection_end(CollectionPropertyIterator *iter)
1050 {
1051         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1052
1053         if(iter->idprop)
1054                 rna_iterator_array_end(iter);
1055         else
1056                 cprop->end(iter);
1057 }
1058
1059 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
1060 {
1061         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1062         IDProperty *idprop;
1063
1064         if((idprop=rna_idproperty_check(&prop, ptr))) {
1065                 return idprop->len;
1066         }
1067         else if(cprop->length) {
1068                 return cprop->length(ptr);
1069         }
1070         else {
1071                 CollectionPropertyIterator iter;
1072                 int length= 0;
1073
1074                 RNA_property_collection_begin(ptr, prop, &iter);
1075                 for(; iter.valid; RNA_property_collection_next(&iter))
1076                         length++;
1077                 RNA_property_collection_end(&iter);
1078
1079                 return length;
1080         }
1081 }
1082
1083 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
1084 {
1085         IDProperty *idprop;
1086
1087         if((idprop=rna_idproperty_check(&prop, ptr))) {
1088                 IDPropertyTemplate val;
1089                 IDProperty *item;
1090                 val.i= 0;
1091
1092                 item= IDP_New(IDP_GROUP, val, "");
1093                 IDP_AppendArray(idprop, item);
1094                 IDP_FreeProperty(item);
1095                 MEM_freeN(item);
1096         }
1097         else if(prop->flag & PROP_IDPROPERTY) {
1098                 IDProperty *group, *item;
1099                 IDPropertyTemplate val;
1100                 val.i= 0;
1101
1102                 group= rna_idproperties_get(ptr, 1);
1103                 if(group) {
1104                         idprop= IDP_NewIDPArray(prop->identifier);
1105                         IDP_AddToGroup(group, idprop);
1106
1107                         item= IDP_New(IDP_GROUP, val, "");
1108                         IDP_AppendArray(idprop, item);
1109                         IDP_FreeProperty(item);
1110                         MEM_freeN(item);
1111                 }
1112         }
1113         else
1114                 printf("RNA_property_collection_add %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
1115
1116         if(r_ptr) {
1117                 if(idprop) {
1118                         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1119
1120                         r_ptr->data= IDP_GetIndexArray(idprop, idprop->len-1);
1121                         r_ptr->type= cprop->structtype;
1122                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
1123                 }
1124                 else
1125                         memset(r_ptr, 0, sizeof(*r_ptr));
1126         }
1127 }
1128
1129 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
1130 {
1131         IDProperty *idprop;
1132
1133         if((idprop=rna_idproperty_check(&prop, ptr)))
1134                 IDP_ResizeIDPArray(idprop, 0);
1135 }
1136
1137 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
1138 {
1139         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1140
1141         if(cprop->lookupint) {
1142                 /* we have a callback defined, use it */
1143                 *r_ptr= cprop->lookupint(ptr, key);
1144                 return (r_ptr->data != NULL);
1145         }
1146         else {
1147                 /* no callback defined, just iterate and find the nth item */
1148                 CollectionPropertyIterator iter;
1149                 int i;
1150
1151                 RNA_property_collection_begin(ptr, prop, &iter);
1152                 for(i=0; iter.valid; RNA_property_collection_next(&iter), i++) {
1153                         if(i == key) {
1154                                 *r_ptr= iter.ptr;
1155                                 break;
1156                         }
1157                 }
1158                 RNA_property_collection_end(&iter);
1159
1160                 if(!iter.valid)
1161                         memset(r_ptr, 0, sizeof(*r_ptr));
1162
1163                 return iter.valid;
1164         }
1165 }
1166
1167 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
1168 {
1169         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1170
1171         if(cprop->lookupstring) {
1172                 /* we have a callback defined, use it */
1173                 *r_ptr= cprop->lookupstring(ptr, key);
1174                 return (r_ptr->data != NULL);
1175         }
1176         else {
1177                 /* no callback defined, compare with name properties if they exist */
1178                 CollectionPropertyIterator iter;
1179                 PropertyRNA *nameprop;
1180                 char name[256], *nameptr;
1181                 int found= 0;
1182
1183                 RNA_property_collection_begin(ptr, prop, &iter);
1184                 for(; iter.valid; RNA_property_collection_next(&iter)) {
1185                         if(iter.ptr.data && iter.ptr.type->nameproperty) {
1186                                 nameprop= iter.ptr.type->nameproperty;
1187
1188                                 nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
1189
1190                                 if(strcmp(nameptr, key) == 0) {
1191                                         *r_ptr= iter.ptr;
1192                                         found= 1;
1193                                 }
1194
1195                                 if ((char *)&name != nameptr)
1196                                         MEM_freeN(nameptr);
1197
1198                                 if(found)
1199                                         break;
1200                         }
1201                 }
1202                 RNA_property_collection_end(&iter);
1203
1204                 if(!iter.valid)
1205                         memset(r_ptr, 0, sizeof(*r_ptr));
1206
1207                 return iter.valid;
1208         }
1209 }
1210
1211 /* Standard iterator functions */
1212
1213 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
1214 {
1215         ListBaseIterator *internal;
1216
1217         internal= MEM_callocN(sizeof(ListBaseIterator), "ListBaseIterator");
1218         internal->link= lb->first;
1219         internal->skip= skip;
1220
1221         iter->internal= internal;
1222         iter->valid= (internal->link != NULL);
1223
1224         if(skip && iter->valid && skip(iter, internal->link))
1225                 rna_iterator_listbase_next(iter);
1226 }
1227
1228 void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
1229 {
1230         ListBaseIterator *internal= iter->internal;
1231
1232         if(internal->skip) {
1233                 do {
1234                         internal->link= internal->link->next;
1235                         iter->valid= (internal->link != NULL);
1236                 } while(iter->valid && internal->skip(iter, internal->link));
1237         }
1238         else {
1239                 internal->link= internal->link->next;
1240                 iter->valid= (internal->link != NULL);
1241         }
1242 }
1243
1244 void *rna_iterator_listbase_get(CollectionPropertyIterator *iter)
1245 {
1246         ListBaseIterator *internal= iter->internal;
1247
1248         return internal->link;
1249 }
1250
1251 void rna_iterator_listbase_end(CollectionPropertyIterator *iter)
1252 {
1253         MEM_freeN(iter->internal);
1254 }
1255
1256 void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int itemsize, int length, IteratorSkipFunc skip)
1257 {
1258         ArrayIterator *internal;
1259
1260         if(ptr == NULL)
1261                 length= 0;
1262
1263         internal= MEM_callocN(sizeof(ArrayIterator), "ArrayIterator");
1264         internal->ptr= ptr;
1265         internal->endptr= ((char*)ptr)+length*itemsize;
1266         internal->itemsize= itemsize;
1267         internal->skip= skip;
1268
1269         iter->internal= internal;
1270         iter->valid= (internal->ptr != internal->endptr);
1271
1272         if(skip && iter->valid && skip(iter, internal->ptr))
1273                 rna_iterator_array_next(iter);
1274 }
1275
1276 void rna_iterator_array_next(CollectionPropertyIterator *iter)
1277 {
1278         ArrayIterator *internal= iter->internal;
1279
1280         if(internal->skip) {
1281                 do {
1282                         internal->ptr += internal->itemsize;
1283                         iter->valid= (internal->ptr != internal->endptr);
1284                 } while(iter->valid && internal->skip(iter, internal->ptr));
1285         }
1286         else {
1287                 internal->ptr += internal->itemsize;
1288                 iter->valid= (internal->ptr != internal->endptr);
1289         }
1290 }
1291
1292 void *rna_iterator_array_get(CollectionPropertyIterator *iter)
1293 {
1294         ArrayIterator *internal= iter->internal;
1295
1296         return internal->ptr;
1297 }
1298
1299 void *rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
1300 {
1301         ArrayIterator *internal= iter->internal;
1302
1303         /* for ** arrays */
1304         return *(void**)(internal->ptr);
1305 }
1306
1307 void rna_iterator_array_end(CollectionPropertyIterator *iter)
1308 {
1309         MEM_freeN(iter->internal);
1310 }
1311
1312 /* Pointer Handling */
1313
1314 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
1315 {
1316         PointerRNA result;
1317
1318         if(data) {
1319                 result.data= data;
1320                 result.type= type;
1321                 rna_pointer_inherit_id(type, ptr, &result);
1322
1323                 if(type->refine)
1324                         result.type= type->refine(&result);
1325         }
1326         else
1327                 memset(&result, 0, sizeof(result));
1328         
1329         return result;
1330 }
1331
1332 /* RNA Path - Experiment */
1333
1334 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
1335 {
1336         const char *p;
1337         char *buf;
1338         int i, j, len, escape;
1339
1340         len= 0;
1341
1342         if(bracket) {
1343                 /* get data between [], check escaping ] with \] */
1344                 if(**path == '[') (*path)++;
1345                 else return NULL;
1346
1347                 p= *path;
1348
1349                 escape= 0;
1350                 while(*p && (*p != ']' || escape)) {
1351                         escape= (*p == '\\');
1352                         len++;
1353                         p++;
1354                 }
1355
1356                 if(*p != ']') return NULL;
1357         }
1358         else {
1359                 /* get data until . or [ */
1360                 p= *path;
1361
1362                 while(*p && *p != '.' && *p != '[') {
1363                         len++;
1364                         p++;
1365                 }
1366         }
1367         
1368         /* empty, return */
1369         if(len == 0)
1370                 return NULL;
1371         
1372         /* try to use fixed buffer if possible */
1373         if(len+1 < fixedlen)
1374                 buf= fixedbuf;
1375         else
1376                 buf= MEM_callocN(sizeof(char)*(len+1), "rna_path_token");
1377
1378         /* copy string, taking into account escaped ] */
1379         for(p=*path, i=0, j=0; i<len; i++, p++) {
1380                 if(*p == '\\' && *(p+1) == ']');
1381                 else buf[j++]= *p;
1382         }
1383
1384         buf[j]= 0;
1385
1386         /* set path to start of next token */
1387         if(*p == ']') p++;
1388         if(*p == '.') p++;
1389         *path= p;
1390
1391         return buf;
1392 }
1393
1394 int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
1395 {
1396         CollectionPropertyIterator iter;
1397         PropertyRNA *prop, *iterprop;
1398         PointerRNA curptr, nextptr;
1399         char fixedbuf[256], *token;
1400         int len, intkey;
1401
1402         prop= NULL;
1403         curptr= *ptr;
1404
1405         while(*path) {
1406                 /* look up property name in current struct */
1407                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 0);
1408
1409                 if(!token)
1410                         return 0;
1411
1412                 iterprop= RNA_struct_iterator_property(&curptr);
1413                 RNA_property_collection_begin(&curptr, iterprop, &iter);
1414                 prop= NULL;
1415
1416                 for(; iter.valid; RNA_property_collection_next(&iter)) {
1417                         if(strcmp(token, RNA_property_identifier(&iter.ptr, iter.ptr.data)) == 0) {
1418                                 prop= iter.ptr.data;
1419                                 break;
1420                         }
1421                 }
1422
1423                 RNA_property_collection_end(&iter);
1424
1425                 if(token != fixedbuf)
1426                         MEM_freeN(token);
1427
1428                 if(!prop)
1429                         return 0;
1430
1431                 /* now look up the value of this property if it is a pointer or
1432                  * collection, otherwise return the property rna so that the
1433                  * caller can read the value of the property itself */
1434                 if(RNA_property_type(&curptr, prop) == PROP_POINTER) {
1435                         nextptr= RNA_property_pointer_get(&curptr, prop);
1436
1437                         if(nextptr.data)
1438                                 curptr= nextptr;
1439                         else
1440                                 return 0;
1441                 }
1442                 else if(RNA_property_type(&curptr, prop) == PROP_COLLECTION && *path) {
1443                         /* resolve the lookup with [] brackets */
1444                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
1445
1446                         if(!token)
1447                                 return 0;
1448
1449                         len= strlen(token);
1450                         
1451                         /* check for "" to see if it is a string */
1452                         if(len >= 2 && token[0] == '"' && token[len-1] == '"') {
1453                                 /* strip away "" */
1454                                 token[len-1]= 0;
1455                                 RNA_property_collection_lookup_string(&curptr, prop, token+1, &nextptr);
1456                         }
1457                         else {
1458                                 /* otherwise do int lookup */
1459                                 intkey= atoi(token);
1460                                 RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr);
1461                         }
1462
1463                         if(token != fixedbuf)
1464                                 MEM_freeN(token);
1465
1466                         if(nextptr.data)
1467                                 curptr= nextptr;
1468                         else
1469                                 return 0;
1470                 }
1471         }
1472
1473         *r_ptr= curptr;
1474         *r_prop= prop;
1475
1476         return 1;
1477 }
1478
1479 char *RNA_path_append(const char *path, PointerRNA *ptr, PropertyRNA *prop, int intkey, const char *strkey)
1480 {
1481         DynStr *dynstr;
1482         const char *s;
1483         char appendstr[128], *result;
1484         
1485         dynstr= BLI_dynstr_new();
1486
1487         /* add .identifier */
1488         if(path) {
1489                 BLI_dynstr_append(dynstr, (char*)path);
1490                 if(*path)
1491                         BLI_dynstr_append(dynstr, ".");
1492         }
1493
1494         BLI_dynstr_append(dynstr, (char*)RNA_property_identifier(ptr, prop));
1495
1496         if(RNA_property_type(ptr, prop) == PROP_COLLECTION) {
1497                 /* add ["strkey"] or [intkey] */
1498                 BLI_dynstr_append(dynstr, "[");
1499
1500                 if(strkey) {
1501                         BLI_dynstr_append(dynstr, "\"");
1502                         for(s=strkey; *s; s++) {
1503                                 if(*s == '[') {
1504                                         appendstr[0]= '\\';
1505                                         appendstr[1]= *s;
1506                                         appendstr[2]= 0;
1507                                 }
1508                                 else {
1509                                         appendstr[0]= *s;
1510                                         appendstr[1]= 0;
1511                                 }
1512                                 BLI_dynstr_append(dynstr, appendstr);
1513                         }
1514                         BLI_dynstr_append(dynstr, "\"");
1515                 }
1516                 else {
1517                         sprintf(appendstr, "%d", intkey);
1518                         BLI_dynstr_append(dynstr, appendstr);
1519                 }
1520
1521                 BLI_dynstr_append(dynstr, "]");
1522         }
1523
1524         result= BLI_dynstr_get_cstring(dynstr);
1525         BLI_dynstr_free(dynstr);
1526
1527         return result;
1528 }
1529
1530 char *RNA_path_back(const char *path)
1531 {
1532         char fixedbuf[256];
1533         const char *previous, *current;
1534         char *result, *token;
1535         int i;
1536
1537         if(!path)
1538                 return NULL;
1539
1540         previous= NULL;
1541         current= path;
1542
1543         /* parse token by token until the end, then we back up to the previous
1544          * position and strip of the next token to get the path one step back */
1545         while(*current) {
1546                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 0);
1547
1548                 if(!token)
1549                         return NULL;
1550                 if(token != fixedbuf)
1551                         MEM_freeN(token);
1552
1553                 /* in case of collection we also need to strip off [] */
1554                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 1);
1555                 if(token && token != fixedbuf)
1556                         MEM_freeN(token);
1557                 
1558                 if(!*current)
1559                         break;
1560
1561                 previous= current;
1562         }
1563
1564         if(!previous)
1565                 return NULL;
1566
1567         /* copy and strip off last token */
1568         i= previous - path;
1569         result= BLI_strdup(path);
1570
1571         if(i > 0 && result[i-1] == '.') i--;
1572         result[i]= 0;
1573
1574         return result;
1575 }
1576
1577 /* Quick name based property access */
1578
1579 int RNA_boolean_get(PointerRNA *ptr, const char *name)
1580 {
1581         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1582
1583         if(prop) {
1584                 return RNA_property_boolean_get(ptr, prop);
1585         }
1586         else {
1587                 printf("RNA_boolean_get: %s.%s not found.\n", ptr->type->identifier, name);
1588                 return 0;
1589         }
1590 }
1591
1592 void RNA_boolean_set(PointerRNA *ptr, const char *name, int value)
1593 {
1594         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1595
1596         if(prop)
1597                 RNA_property_boolean_set(ptr, prop, value);
1598         else
1599                 printf("RNA_boolean_set: %s.%s not found.\n", ptr->type->identifier, name);
1600 }
1601
1602 void RNA_boolean_get_array(PointerRNA *ptr, const char *name, int *values)
1603 {
1604         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1605
1606         if(prop)
1607                 RNA_property_boolean_get_array(ptr, prop, values);
1608         else
1609                 printf("RNA_boolean_get_array: %s.%s not found.\n", ptr->type->identifier, name);
1610 }
1611
1612 void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const int *values)
1613 {
1614         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1615
1616         if(prop)
1617                 RNA_property_boolean_set_array(ptr, prop, values);
1618         else
1619                 printf("RNA_boolean_set_array: %s.%s not found.\n", ptr->type->identifier, name);
1620 }
1621
1622 int RNA_int_get(PointerRNA *ptr, const char *name)
1623 {
1624         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1625
1626         if(prop) {
1627                 return RNA_property_int_get(ptr, prop);
1628         }
1629         else {
1630                 printf("RNA_int_get: %s.%s not found.\n", ptr->type->identifier, name);
1631                 return 0;
1632         }
1633 }
1634
1635 void RNA_int_set(PointerRNA *ptr, const char *name, int value)
1636 {
1637         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1638
1639         if(prop)
1640                 RNA_property_int_set(ptr, prop, value);
1641         else
1642                 printf("RNA_int_set: %s.%s not found.\n", ptr->type->identifier, name);
1643 }
1644
1645 void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
1646 {
1647         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1648
1649         if(prop)
1650                 RNA_property_int_get_array(ptr, prop, values);
1651         else
1652                 printf("RNA_int_get_array: %s.%s not found.\n", ptr->type->identifier, name);
1653 }
1654
1655 void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
1656 {
1657         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1658
1659         if(prop)
1660                 RNA_property_int_set_array(ptr, prop, values);
1661         else
1662                 printf("RNA_int_set_array: %s.%s not found.\n", ptr->type->identifier, name);
1663 }
1664
1665 float RNA_float_get(PointerRNA *ptr, const char *name)
1666 {
1667         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1668
1669         if(prop) {
1670                 return RNA_property_float_get(ptr, prop);
1671         }
1672         else {
1673                 printf("RNA_float_get: %s.%s not found.\n", ptr->type->identifier, name);
1674                 return 0;
1675         }
1676 }
1677
1678 void RNA_float_set(PointerRNA *ptr, const char *name, float value)
1679 {
1680         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1681
1682         if(prop)
1683                 RNA_property_float_set(ptr, prop, value);
1684         else
1685                 printf("RNA_float_set: %s.%s not found.\n", ptr->type->identifier, name);
1686 }
1687
1688 void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
1689 {
1690         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1691
1692         if(prop)
1693                 RNA_property_float_get_array(ptr, prop, values);
1694         else
1695                 printf("RNA_float_get_array: %s.%s not found.\n", ptr->type->identifier, name);
1696 }
1697
1698 void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
1699 {
1700         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1701
1702         if(prop)
1703                 RNA_property_float_set_array(ptr, prop, values);
1704         else
1705                 printf("RNA_float_set_array: %s.%s not found.\n", ptr->type->identifier, name);
1706 }
1707
1708 int RNA_enum_get(PointerRNA *ptr, const char *name)
1709 {
1710         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1711
1712         if(prop) {
1713                 return RNA_property_enum_get(ptr, prop);
1714         }
1715         else {
1716                 printf("RNA_enum_get: %s.%s not found.\n", ptr->type->identifier, name);
1717                 return 0;
1718         }
1719 }
1720
1721 void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
1722 {
1723         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1724
1725         if(prop)
1726                 RNA_property_enum_set(ptr, prop, value);
1727         else
1728                 printf("RNA_enum_set: %s.%s not found.\n", ptr->type->identifier, name);
1729 }
1730
1731 int RNA_enum_is_equal(PointerRNA *ptr, const char *name, const char *enumname)
1732 {
1733         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1734         const EnumPropertyItem *item;
1735         int a, totitem;
1736
1737         if(prop) {
1738                 RNA_property_enum_items(ptr, prop, &item, &totitem);
1739
1740                 for(a=0; a<totitem; a++)
1741                         if(strcmp(item[a].identifier, enumname) == 0)
1742                                 return (item[a].value == RNA_property_enum_get(ptr, prop));
1743
1744                 printf("RNA_enum_is_equal: %s.%s item %s not found.\n", ptr->type->identifier, name, enumname);
1745                 return 0;
1746         }
1747         else {
1748                 printf("RNA_enum_is_equal: %s.%s not found.\n", ptr->type->identifier, name);
1749                 return 0;
1750         }
1751 }
1752
1753 void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
1754 {
1755         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1756
1757         if(prop)
1758                 RNA_property_string_get(ptr, prop, value);
1759         else
1760                 printf("RNA_string_get: %s.%s not found.\n", ptr->type->identifier, name);
1761 }
1762
1763 char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen)
1764 {
1765         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1766
1767         if(prop) {
1768                 return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen);
1769         }
1770         else {
1771                 printf("RNA_string_get_alloc: %s.%s not found.\n", ptr->type->identifier, name);
1772                 return 0;
1773         }
1774 }
1775
1776 int RNA_string_length(PointerRNA *ptr, const char *name)
1777 {
1778         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1779
1780         if(prop) {
1781                 return RNA_property_string_length(ptr, prop);
1782         }
1783         else {
1784                 printf("RNA_string_length: %s.%s not found.\n", ptr->type->identifier, name);
1785                 return 0;
1786         }
1787 }
1788
1789 void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
1790 {
1791         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1792
1793         if(prop)
1794                 RNA_property_string_set(ptr, prop, value);
1795         else
1796                 printf("RNA_string_set: %s.%s not found.\n", ptr->type->identifier, name);
1797 }
1798
1799 PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
1800 {
1801         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1802
1803         if(prop) {
1804                 return RNA_property_pointer_get(ptr, prop);
1805         }
1806         else {
1807                 PointerRNA result;
1808
1809                 printf("RNA_pointer_get: %s.%s not found.\n", ptr->type->identifier, name);
1810
1811                 memset(&result, 0, sizeof(result));
1812                 return result;
1813         }
1814 }
1815
1816 void RNA_pointer_add(PointerRNA *ptr, const char *name)
1817 {
1818         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1819
1820         if(prop)
1821                 RNA_property_pointer_add(ptr, prop);
1822         else
1823                 printf("RNA_pointer_set: %s.%s not found.\n", ptr->type->identifier, name);
1824 }
1825
1826 void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter)
1827 {
1828         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1829
1830         if(prop)
1831                 RNA_property_collection_begin(ptr, prop, iter);
1832         else
1833                 printf("RNA_collection_begin: %s.%s not found.\n", ptr->type->identifier, name);
1834 }
1835
1836 void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
1837 {
1838         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1839
1840         if(prop)
1841                 RNA_property_collection_add(ptr, prop, r_value);
1842         else
1843                 printf("RNA_collection_add: %s.%s not found.\n", ptr->type->identifier, name);
1844 }
1845
1846 void RNA_collection_clear(PointerRNA *ptr, const char *name)
1847 {
1848         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1849
1850         if(prop)
1851                 RNA_property_collection_clear(ptr, prop);
1852         else
1853                 printf("RNA_collection_clear: %s.%s not found.\n", ptr->type->identifier, name);
1854 }
1855
1856 int RNA_collection_length(PointerRNA *ptr, const char *name)
1857 {
1858         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1859
1860         if(prop) {
1861                 return RNA_property_collection_length(ptr, prop);
1862         }
1863         else {
1864                 printf("RNA_collection_length: %s.%s not found.\n", ptr->type->identifier, name);
1865                 return 0;
1866         }
1867 }
1868
1869 int RNA_property_is_set(PointerRNA *ptr, const char *name)
1870 {
1871         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
1872
1873         if(prop) {
1874                 return (rna_idproperty_find(ptr, name) != NULL);
1875         }
1876         else {
1877                 printf("RNA_property_is_set: %s.%s not found.\n", ptr->type->identifier, name);
1878                 return 0;
1879         }
1880 }
1881
1882 /* string representation of a property, python
1883  * compatible but can be used for display too*/
1884 char *RNA_property_as_string(PointerRNA *ptr, PropertyRNA *prop)
1885 {
1886         int type = RNA_property_type(ptr, prop);
1887         int len = RNA_property_array_length(ptr, prop);
1888         int i;
1889
1890         DynStr *dynstr= BLI_dynstr_new();
1891         char *cstring;
1892         
1893
1894         /* see if we can coorce into a python type - PropertyType */
1895         switch (type) {
1896         case PROP_BOOLEAN:
1897                 if (len==0) {
1898                         BLI_dynstr_append(dynstr, RNA_property_boolean_get(ptr, prop) ? "True" : "False");
1899                 }
1900                 else {
1901                         BLI_dynstr_append(dynstr, "(");
1902                         for(i=0; i<len; i++) {
1903                                 BLI_dynstr_appendf(dynstr, i?", %s":"%s", RNA_property_boolean_get_index(ptr, prop, i) ? "True" : "False");
1904                         }
1905                         BLI_dynstr_append(dynstr, ")");
1906                 }
1907                 break;
1908         case PROP_INT:
1909                 if (len==0) {
1910                         BLI_dynstr_appendf(dynstr, "%d", RNA_property_int_get(ptr, prop));
1911                 }
1912                 else {
1913                         BLI_dynstr_append(dynstr, "(");
1914                         for(i=0; i<len; i++) {
1915                                 BLI_dynstr_appendf(dynstr, i?", %d":"%d", RNA_property_int_get_index(ptr, prop, i));
1916                         }
1917                         BLI_dynstr_append(dynstr, ")");
1918                 }
1919                 break;
1920         case PROP_FLOAT:
1921                 if (len==0) {
1922                         BLI_dynstr_appendf(dynstr, "%g", RNA_property_float_get(ptr, prop));
1923                 }
1924                 else {
1925                         BLI_dynstr_append(dynstr, "(");
1926                         for(i=0; i<len; i++) {
1927                                 BLI_dynstr_appendf(dynstr, i?", %g":"%g", RNA_property_float_get_index(ptr, prop, i));
1928                         }
1929                         BLI_dynstr_append(dynstr, ")");
1930                 }
1931                 break;
1932         case PROP_STRING:
1933         {
1934                 /* string arrays dont exist */
1935                 char *buf;
1936                 buf = RNA_property_string_get_alloc(ptr, prop, NULL, -1);
1937                 BLI_dynstr_appendf(dynstr, "\"%s\"", buf);
1938                 MEM_freeN(buf);
1939                 break;
1940         }
1941         case PROP_ENUM:
1942         {
1943                 /* string arrays dont exist */
1944                 const char *identifier;
1945                 int val = RNA_property_enum_get(ptr, prop);
1946
1947                 if (RNA_property_enum_identifier(ptr, prop, val, &identifier)) {
1948                         BLI_dynstr_appendf(dynstr, "'%s'", identifier);
1949                 }
1950                 else {
1951                         BLI_dynstr_appendf(dynstr, "'<UNKNOWN ENUM>'", identifier);
1952                 }
1953                 break;
1954         }
1955         case PROP_POINTER:
1956         {
1957                 BLI_dynstr_append(dynstr, "'<POINTER>'"); /* TODO */
1958                 break;
1959         }
1960         case PROP_COLLECTION:
1961                 BLI_dynstr_append(dynstr, "'<COLLECTION>'"); /* TODO */
1962                 break;
1963         default:
1964                 BLI_dynstr_append(dynstr, "'<UNKNOWN TYPE>'"); /* TODO */
1965                 break;
1966         }
1967
1968         cstring = BLI_dynstr_get_cstring(dynstr);
1969         BLI_dynstr_free(dynstr);
1970         return cstring;
1971 }
1972