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