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