53f5407e521c389c84f09eaec2245287a63cc488
[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 #include <ctype.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_ID.h"
32 #include "DNA_scene_types.h"
33 #include "DNA_windowmanager_types.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_dynstr.h"
37 #include "BLI_ghash.h"
38
39 #include "BKE_context.h"
40 #include "BKE_idprop.h"
41 #include "BKE_main.h"
42 #include "BKE_report.h"
43 #include "BKE_utildefines.h"
44
45 #include "WM_api.h"
46
47 #include "RNA_access.h"
48 #include "RNA_define.h"
49 #include "RNA_types.h"
50
51 /* flush updates */
52 #include "DNA_object_types.h"
53 #include "BKE_depsgraph.h"
54 #include "WM_types.h"
55
56 #include "rna_internal.h"
57
58 /* Init/Exit */
59
60 void RNA_init()
61 {
62         StructRNA *srna;
63         PropertyRNA *prop;
64
65         for(srna=BLENDER_RNA.structs.first; srna; srna=srna->cont.next) {
66                 if(!srna->cont.prophash) {
67                         srna->cont.prophash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp);
68
69                         for(prop=srna->cont.properties.first; prop; prop=prop->next)
70                                 if(!(prop->flag & PROP_BUILTIN))
71                                         BLI_ghash_insert(srna->cont.prophash, (void*)prop->identifier, prop);
72                 }
73         }
74 }
75
76 void RNA_exit()
77 {
78         StructRNA *srna;
79
80         for(srna=BLENDER_RNA.structs.first; srna; srna=srna->cont.next) {
81                 if(srna->cont.prophash) {
82                         BLI_ghash_free(srna->cont.prophash, NULL, NULL);
83                         srna->cont.prophash= NULL;
84                 }
85         }
86
87         RNA_free(&BLENDER_RNA);
88 }
89
90 /* Pointer */
91
92 PointerRNA PointerRNA_NULL = {{0}, 0, 0};
93
94 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
95 {
96         r_ptr->id.data= NULL;
97         r_ptr->type= &RNA_Main;
98         r_ptr->data= main;
99 }
100
101 void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
102 {
103         PointerRNA tmp;
104         StructRNA *type, *idtype= NULL;
105
106         if(id) {
107                 memset(&tmp, 0, sizeof(tmp));
108                 tmp.data= id;
109                 idtype= rna_ID_refine(&tmp);
110                 
111                 while(idtype->refine) {
112                         type= idtype->refine(&tmp);
113
114                         if(type == idtype)
115                                 break;
116                         else
117                                 idtype= type;
118                 }
119         }
120         
121         r_ptr->id.data= id;
122         r_ptr->type= idtype;
123         r_ptr->data= id;
124 }
125
126 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
127 {
128         PointerRNA tmp;
129         StructRNA *idtype= NULL;
130
131         if(id) {
132                 memset(&tmp, 0, sizeof(tmp));
133                 tmp.data= id;
134                 idtype= rna_ID_refine(&tmp);
135         }
136
137         r_ptr->id.data= id;
138         r_ptr->type= type;
139         r_ptr->data= data;
140
141         if(data) {
142                 while(r_ptr->type && r_ptr->type->refine) {
143                         StructRNA *rtype= r_ptr->type->refine(r_ptr);
144
145                         if(rtype == r_ptr->type)
146                                 break;
147                         else
148                                 r_ptr->type= rtype;
149                 }
150         }
151 }
152
153 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
154 {
155         if(type && type->flag & STRUCT_ID) {
156                 ptr->id.data= ptr->data;
157         }
158         else {
159                 ptr->id.data= parent->id.data;
160         }
161 }
162
163 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
164 {
165         r_ptr->id.data= NULL;
166         r_ptr->type= &RNA_BlenderRNA;
167         r_ptr->data= &BLENDER_RNA;
168 }
169
170 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
171 {
172         PointerRNA result;
173
174         if(data) {
175                 result.data= data;
176                 result.type= type;
177                 rna_pointer_inherit_id(type, ptr, &result);
178
179                 while(result.type->refine) {
180                         type= result.type->refine(&result);
181
182                         if(type == result.type)
183                                 break;
184                         else
185                                 result.type= type;
186                 }
187         }
188         else
189                 memset(&result, 0, sizeof(result));
190         
191         return result;
192 }
193
194 /* ID Properties */
195
196 /* return a UI local ID prop definition for this prop */
197 IDProperty *rna_idproperty_ui(PropertyRNA *prop)
198 {
199         IDProperty *idprop;
200
201         for(idprop= ((IDProperty *)prop)->prev; idprop; idprop= idprop->prev) {
202                 if (strcmp(RNA_IDP_UI, idprop->name)==0)
203                         break;
204         }
205
206         if(idprop==NULL) {
207                 for(idprop= ((IDProperty *)prop)->next; idprop; idprop= idprop->next) {
208                         if (strcmp(RNA_IDP_UI, idprop->name)==0)
209                                 break;
210                 }
211         }
212
213         if (idprop)
214                 return IDP_GetPropertyFromGroup(idprop, ((IDProperty *)prop)->name);
215
216         return NULL;
217 }
218
219 IDProperty *RNA_struct_idproperties(PointerRNA *ptr, int create)
220 {
221         StructRNA *type= ptr->type;
222
223         if(type && type->idproperties)
224                 return type->idproperties(ptr, create);
225         
226         return NULL;
227 }
228
229 int RNA_struct_idproperties_check(PointerRNA *ptr)
230 {
231         StructRNA *type= ptr->type;
232         return (type && type->idproperties) ? 1 : 0;
233 }
234
235 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
236 {
237         IDProperty *group= RNA_struct_idproperties(ptr, 0);
238         IDProperty *idprop;
239
240         if(group) {
241                 for(idprop=group->data.group.first; idprop; idprop=idprop->next)
242                         if(strcmp(idprop->name, name) == 0)
243                                 return idprop;
244         }
245         
246         return NULL;
247 }
248
249 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
250 {
251         if(prop->magic == RNA_MAGIC) {
252                 int arraylen[RNA_MAX_ARRAY_DIMENSION];
253                 return (prop->getlength)? prop->getlength(ptr, arraylen): prop->totarraylength;
254         }
255         else {
256                 IDProperty *idprop= (IDProperty*)prop;
257
258                 if(idprop->type == IDP_ARRAY)
259                         return idprop->len;
260                 else
261                         return 0;
262         }
263 }
264
265 static int rna_ensure_property_array_check(PointerRNA *ptr, PropertyRNA *prop)
266 {
267         if(prop->magic == RNA_MAGIC) {
268                 return (prop->getlength || prop->totarraylength) ? 1:0;
269         }
270         else {
271                 IDProperty *idprop= (IDProperty*)prop;
272
273                 return idprop->type == IDP_ARRAY ? 1:0;
274         }
275 }
276
277 static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int length[])
278 {
279         if(prop->magic == RNA_MAGIC) {
280                 if(prop->getlength)
281                         prop->getlength(ptr, length);
282                 else
283                         memcpy(length, prop->arraylength, prop->arraydimension*sizeof(int));
284         }
285         else {
286                 IDProperty *idprop= (IDProperty*)prop;
287
288                 if(idprop->type == IDP_ARRAY)
289                         length[0]= idprop->len;
290                 else
291                         length[0]= 0;
292         }
293 }
294
295 static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
296 {
297         /* this verifies if the idproperty actually matches the property
298          * description and otherwise removes it. this is to ensure that
299          * rna property access is type safe, e.g. if you defined the rna
300          * to have a certain array length you can count on that staying so */
301         
302         switch(idprop->type) {
303                 case IDP_IDPARRAY:
304                         if(prop->type != PROP_COLLECTION)
305                                 return 0;
306                         break;
307                 case IDP_ARRAY:
308                         if(rna_ensure_property_array_length(ptr, prop) != idprop->len)
309                                 return 0;
310
311                         if(idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
312                                 return 0;
313                         if(idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
314                                 return 0;
315
316                         break;
317                 case IDP_INT:
318                         if(!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
319                                 return 0;
320                         break;
321                 case IDP_FLOAT:
322                 case IDP_DOUBLE:
323                         if(prop->type != PROP_FLOAT)
324                                 return 0;
325                         break;
326                 case IDP_STRING:
327                         if(prop->type != PROP_STRING)
328                                 return 0;
329                         break;
330                 case IDP_GROUP:
331                         if(prop->type != PROP_POINTER)
332                                 return 0;
333                         break;
334                 default:
335                         return 0;
336         }
337
338         return 1;
339 }
340
341 static PropertyRNA *typemap[IDP_NUMTYPES] =
342         {(PropertyRNA*)&rna_IDProperty_string,
343          (PropertyRNA*)&rna_IDProperty_int,
344          (PropertyRNA*)&rna_IDProperty_float,
345          NULL, NULL, NULL,
346          (PropertyRNA*)&rna_IDProperty_group, NULL,
347          (PropertyRNA*)&rna_IDProperty_double};
348
349 static PropertyRNA *arraytypemap[IDP_NUMTYPES] =
350         {NULL, (PropertyRNA*)&rna_IDProperty_int_array,
351          (PropertyRNA*)&rna_IDProperty_float_array,
352          NULL, NULL, NULL,
353          (PropertyRNA*)&rna_IDProperty_collection, NULL,
354          (PropertyRNA*)&rna_IDProperty_double_array};
355
356 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
357 {
358         /* This is quite a hack, but avoids some complexity in the API. we
359          * pass IDProperty structs as PropertyRNA pointers to the outside.
360          * We store some bytes in PropertyRNA structs that allows us to
361          * distinguish it from IDProperty structs. If it is an ID property,
362          * we look up an IDP PropertyRNA based on the type, and set the data
363          * pointer to the IDProperty. */
364
365         if((*prop)->magic == RNA_MAGIC) {
366                 if((*prop)->flag & PROP_IDPROPERTY) {
367                         IDProperty *idprop= rna_idproperty_find(ptr, (*prop)->identifier);
368
369                         if(idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) {
370                                 IDProperty *group= RNA_struct_idproperties(ptr, 0);
371
372                                 IDP_RemFromGroup(group, idprop);
373                                 IDP_FreeProperty(idprop);
374                                 MEM_freeN(idprop);
375                                 return NULL;
376                         }
377
378                         return idprop;
379                 }
380                 else
381                         return NULL;
382         }
383
384         {
385                 IDProperty *idprop= (IDProperty*)(*prop);
386
387                 if(idprop->type == IDP_ARRAY)
388                         *prop= arraytypemap[(int)(idprop->subtype)];
389                 else 
390                         *prop= typemap[(int)(idprop->type)];
391
392                 return idprop;
393         }
394 }
395
396 static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
397 {
398         /* the quick version if we don't need the idproperty */
399
400         if(prop->magic == RNA_MAGIC)
401                 return prop;
402
403         {
404                 IDProperty *idprop= (IDProperty*)prop;
405
406                 if(idprop->type == IDP_ARRAY)
407                         return arraytypemap[(int)(idprop->subtype)];
408                 else 
409                         return typemap[(int)(idprop->type)];
410         }
411 }
412
413 static const char *rna_ensure_property_identifier(PropertyRNA *prop)
414 {
415         if(prop->magic == RNA_MAGIC)
416                 return prop->identifier;
417         else
418                 return ((IDProperty*)prop)->name;
419 }
420
421 static const char *rna_ensure_property_description(PropertyRNA *prop)
422 {
423         if(prop->magic == RNA_MAGIC)
424                 return prop->description;
425         else {
426                 /* attempt to get the local ID values */
427                 IDProperty *idp_ui= rna_idproperty_ui(prop);
428
429                 if(idp_ui) { /* TODO, type checking on ID props */
430
431                         IDProperty *item= IDP_GetPropertyFromGroup(idp_ui, "description");
432                         if(item)
433                                 return (char *)item->data.pointer ;
434                 }
435
436                 return ((IDProperty*)prop)->name; /* XXX - not correct */
437         }
438 }
439
440 static const char *rna_ensure_property_name(PropertyRNA *prop)
441 {
442         if(prop->magic == RNA_MAGIC)
443                 return prop->name;
444         else
445                 return ((IDProperty*)prop)->name;
446 }
447
448 /* Structs */
449
450 const char *RNA_struct_identifier(StructRNA *type)
451 {
452         return type->identifier;
453 }
454
455 const char *RNA_struct_ui_name(StructRNA *type)
456 {
457         return type->name;
458 }
459
460 int RNA_struct_ui_icon(StructRNA *type)
461 {
462         if(type)
463                 return type->icon;
464         else
465                 return ICON_DOT;
466 }
467
468 const char *RNA_struct_ui_description(StructRNA *type)
469 {
470         return type->description;
471 }
472
473 PropertyRNA *RNA_struct_name_property(StructRNA *type)
474 {
475         return type->nameproperty;
476 }
477
478 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
479 {
480         return type->iteratorproperty;
481 }
482
483 StructRNA *RNA_struct_base(StructRNA *type)
484 {
485         return type->base;
486 }
487
488 int RNA_struct_is_ID(StructRNA *type)
489 {
490         return (type->flag & STRUCT_ID) != 0;
491 }
492
493 int RNA_struct_is_a(StructRNA *type, StructRNA *srna)
494 {
495         StructRNA *base;
496
497         if(!type)
498                 return 0;
499
500         /* ptr->type is always maximally refined */
501         for(base=type; base; base=base->base)
502                 if(base == srna)
503                         return 1;
504         
505         return 0;
506 }
507
508 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
509 {
510         if(identifier[0]=='[' && identifier[1]=='"') {
511                 /* id prop lookup, not so common */
512                 PropertyRNA *r_prop= NULL;
513                 PointerRNA r_ptr; /* only support single level props */
514                 if(RNA_path_resolve(ptr, identifier, &r_ptr, &r_prop) && r_ptr.type==ptr->type && r_ptr.data==ptr->data)
515                         return r_prop;
516         }
517         else {
518                 /* most common case */
519                 PropertyRNA *iterprop= RNA_struct_iterator_property(ptr->type);
520                 PointerRNA propptr;
521
522                 if(RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr))
523                         return propptr.data;
524         }
525         
526         return NULL;
527 }
528
529 /* Find the property which uses the given nested struct */
530 PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
531 {
532         PropertyRNA *prop= NULL;
533
534         RNA_STRUCT_BEGIN(ptr, iprop) {
535                 /* This assumes that there can only be one user of this nested struct */
536                 if (RNA_property_pointer_type(ptr, iprop) == srna) {
537                         prop= iprop;
538                         break;
539                 }
540         }
541         RNA_PROP_END;
542
543         return prop;
544 }
545
546 const struct ListBase *RNA_struct_defined_properties(StructRNA *srna)
547 {
548         return &srna->cont.properties;
549 }
550
551 FunctionRNA *RNA_struct_find_function(PointerRNA *ptr, const char *identifier)
552 {
553         PointerRNA tptr;
554         PropertyRNA *iterprop;
555         FunctionRNA *func;
556
557         RNA_pointer_create(NULL, &RNA_Struct, ptr->type, &tptr);
558         iterprop= RNA_struct_find_property(&tptr, "functions");
559
560         func= NULL;
561
562         RNA_PROP_BEGIN(&tptr, funcptr, iterprop) {
563                 if(strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
564                         func= funcptr.data;
565                         break;
566                 }
567         }
568         RNA_PROP_END;
569
570         return func;
571 }
572
573 const struct ListBase *RNA_struct_defined_functions(StructRNA *srna)
574 {
575         return &srna->functions;
576 }
577
578 StructRegisterFunc RNA_struct_register(StructRNA *type)
579 {
580         return type->reg;
581 }
582
583 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
584 {
585         do {
586                 if(type->unreg)
587                         return type->unreg;
588         } while((type=type->base));
589
590         return NULL;
591 }
592
593 void *RNA_struct_py_type_get(StructRNA *srna)
594 {
595         return srna->py_type;
596 }
597
598 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
599 {
600         srna->py_type= py_type;
601 }
602
603 void *RNA_struct_blender_type_get(StructRNA *srna)
604 {
605         return srna->blender_type;
606 }
607
608 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
609 {
610         srna->blender_type= blender_type;
611 }
612
613 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen)
614 {
615         PropertyRNA *nameprop;
616
617         if(ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
618                 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen);
619
620         return NULL;
621 }
622
623 /* Property Information */
624
625 const char *RNA_property_identifier(PropertyRNA *prop)
626 {
627         return rna_ensure_property_identifier(prop);
628 }
629
630 const char *RNA_property_description(PropertyRNA *prop)
631 {
632         return rna_ensure_property_description(prop);
633 }
634
635 PropertyType RNA_property_type(PropertyRNA *prop)
636 {
637         return rna_ensure_property(prop)->type;
638 }
639
640 PropertySubType RNA_property_subtype(PropertyRNA *prop)
641 {
642         return rna_ensure_property(prop)->subtype;
643 }
644
645 PropertyUnit RNA_property_unit(PropertyRNA *prop)
646 {
647         return RNA_SUBTYPE_UNIT(rna_ensure_property(prop)->subtype);
648 }
649
650 int RNA_property_flag(PropertyRNA *prop)
651 {
652         return rna_ensure_property(prop)->flag;
653 }
654
655 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
656 {
657         return rna_ensure_property_array_length(ptr, prop);
658 }
659
660 int RNA_property_array_check(PointerRNA *ptr, PropertyRNA *prop)
661 {
662         return rna_ensure_property_array_check(ptr, prop);
663 }
664
665 /* used by BPY to make an array from the python object */
666 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
667 {
668         PropertyRNA *rprop= rna_ensure_property(prop);
669
670         if(length && rprop->arraydimension > 1)
671                 rna_ensure_property_multi_array_length(ptr, prop, length);
672
673         return rprop->arraydimension;
674 }
675
676 /* Return the size of Nth dimension. */
677 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
678 {
679         int len[RNA_MAX_ARRAY_DIMENSION];
680
681         rna_ensure_property_multi_array_length(ptr, prop, len);
682
683         return len[dim];
684 }
685
686 char RNA_property_array_item_char(PropertyRNA *prop, int index)
687 {
688         const char *vectoritem= "XYZW";
689         const char *quatitem= "WXYZ";
690         const char *coloritem= "RGBA";
691         PropertySubType subtype= rna_ensure_property(prop)->subtype;
692
693         /* get string to use for array index */
694         if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE))
695                 return quatitem[index];
696         else if((index < 4) && ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
697                 return vectoritem[index];
698         else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA))
699                 return coloritem[index];
700
701         return '\0';
702 }
703
704 int RNA_property_array_item_index(PropertyRNA *prop, char name)
705 {
706         PropertySubType subtype= rna_ensure_property(prop)->subtype;
707
708         name= toupper(name);
709
710         /* get index based on string name/alias */
711         /* maybe a function to find char index in string would be better than all the switches */
712         if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
713                 switch (name) {
714                         case 'W':
715                                 return 0;
716                         case 'X':
717                                 return 1;
718                         case 'Y':
719                                 return 2;
720                         case 'Z':
721                                 return 3;
722                 }
723         }
724         else if(ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION)) {
725                 switch (name) {
726                         case 'X':
727                                 return 0;
728                         case 'Y':
729                                 return 1;
730                         case 'Z':
731                                 return 2;
732                         case 'W':
733                                 return 3;
734                 }
735         }
736         else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
737                 switch (name) {
738                         case 'R':
739                                 return 0;
740                         case 'G':
741                                 return 1;
742                         case 'B':
743                                 return 2;
744                         case 'A':
745                                 return 3;
746                 }
747         }
748
749         return -1;
750 }
751
752 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
753 {
754         IntPropertyRNA *iprop= (IntPropertyRNA*)rna_ensure_property(prop);
755
756         if(prop->magic != RNA_MAGIC) {
757                 /* attempt to get the local ID values */
758                 IDProperty *idp_ui= rna_idproperty_ui(prop);
759                 IDProperty *item;
760
761                 if(idp_ui) { /* TODO, type checking on ID props */
762                         item= IDP_GetPropertyFromGroup(idp_ui, "min");
763                         *hardmin= item ? item->data.val : INT_MIN;
764
765                         item= IDP_GetPropertyFromGroup(idp_ui, "max");
766                         *hardmax= item ? item->data.val : INT_MAX;
767
768                         return;
769                 }
770         }
771
772         if(iprop->range) {
773                 iprop->range(ptr, hardmin, hardmax);
774         }
775         else {
776                 *hardmin= iprop->hardmin;
777                 *hardmax= iprop->hardmax;
778         }
779 }
780
781 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
782 {
783         IntPropertyRNA *iprop= (IntPropertyRNA*)rna_ensure_property(prop);
784         int hardmin, hardmax;
785         
786         if(prop->magic != RNA_MAGIC) {
787                 /* attempt to get the local ID values */
788                 IDProperty *idp_ui= rna_idproperty_ui(prop);
789                 IDProperty *item;
790
791                 if(idp_ui) { /* TODO, type checking on ID props */
792                         item= IDP_GetPropertyFromGroup(idp_ui, "soft_min");
793                         *softmin= item ? item->data.val : INT_MIN;
794
795                         item= IDP_GetPropertyFromGroup(idp_ui, "soft_max");
796                         *softmax= item ? item->data.val : INT_MAX;
797
798                         item= IDP_GetPropertyFromGroup(idp_ui, "step");
799                         *step= item ? item->data.val : 1;
800
801                         return;
802                 }
803         }
804
805         if(iprop->range) {
806                 iprop->range(ptr, &hardmin, &hardmax);
807                 *softmin= MAX2(iprop->softmin, hardmin);
808                 *softmax= MIN2(iprop->softmax, hardmax);
809         }
810         else {
811                 *softmin= iprop->softmin;
812                 *softmax= iprop->softmax;
813         }
814
815         *step= iprop->step;
816 }
817
818 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
819 {
820         FloatPropertyRNA *fprop= (FloatPropertyRNA*)rna_ensure_property(prop);
821
822         if(prop->magic != RNA_MAGIC) {
823                 /* attempt to get the local ID values */
824                 IDProperty *idp_ui= rna_idproperty_ui(prop);
825                 IDProperty *item;
826
827                 if(idp_ui) { /* TODO, type checking on ID props */
828                         item= IDP_GetPropertyFromGroup(idp_ui, "min");
829                         *hardmin= item ? *(double*)&item->data.val : FLT_MIN;
830
831                         item= IDP_GetPropertyFromGroup(idp_ui, "max");
832                         *hardmax= item ? *(double*)&item->data.val : FLT_MAX;
833
834                         return;
835                 }
836         }
837
838         if(fprop->range) {
839                 fprop->range(ptr, hardmin, hardmax);
840         }
841         else {
842                 *hardmin= fprop->hardmin;
843                 *hardmax= fprop->hardmax;
844         }
845 }
846
847 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax, float *step, float *precision)
848 {
849         FloatPropertyRNA *fprop= (FloatPropertyRNA*)rna_ensure_property(prop);
850         float hardmin, hardmax;
851
852         if(prop->magic != RNA_MAGIC) {
853                 /* attempt to get the local ID values */
854                 IDProperty *idp_ui= rna_idproperty_ui(prop);
855                 IDProperty *item;
856
857                 if(idp_ui) { /* TODO, type checking on ID props */
858                         item= IDP_GetPropertyFromGroup(idp_ui, "soft_min");
859                         *softmin= item ? *(double*)&item->data.val : FLT_MIN;
860
861                         item= IDP_GetPropertyFromGroup(idp_ui, "soft_max");
862                         *softmax= item ? *(double*)&item->data.val : FLT_MAX;
863
864                         item= IDP_GetPropertyFromGroup(idp_ui, "step");
865                         *step= item ? *(double*)&item->data.val : 1.0f;
866
867                         item= IDP_GetPropertyFromGroup(idp_ui, "precision");
868                         *precision= item ? *(double*)&item->data.val : 3.0f;
869
870                         return;
871                 }
872         }
873
874         if(fprop->range) {
875                 fprop->range(ptr, &hardmin, &hardmax);
876                 *softmin= MAX2(fprop->softmin, hardmin);
877                 *softmax= MIN2(fprop->softmax, hardmax);
878         }
879         else {
880                 *softmin= fprop->softmin;
881                 *softmax= fprop->softmax;
882         }
883
884         *step= fprop->step;
885         *precision= (float)fprop->precision;
886 }
887
888 /* this is the max length including \0 terminator */
889 int RNA_property_string_maxlength(PropertyRNA *prop)
890 {
891         StringPropertyRNA *sprop= (StringPropertyRNA*)rna_ensure_property(prop);
892         return sprop->maxlength;
893 }
894
895 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
896 {
897         prop= rna_ensure_property(prop);
898
899         if(prop->type == PROP_POINTER) {
900                 PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
901
902                 if(pprop->typef)
903                         return pprop->typef(ptr);
904                 else if(pprop->type)
905                         return pprop->type;
906         }
907         else if(prop->type == PROP_COLLECTION) {
908                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
909
910                 if(cprop->item_type)
911                         return cprop->item_type;
912         }
913
914         return &RNA_UnknownType;
915 }
916
917 /* Reuse for dynamic types  */
918 EnumPropertyItem DummyRNA_NULL_items[] = {
919         {0, NULL, 0, NULL, NULL}
920 };
921
922 void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free)
923 {
924         EnumPropertyRNA *eprop= (EnumPropertyRNA*)rna_ensure_property(prop);
925
926         *free= 0;
927
928         if(eprop->itemf && C) {
929                 int tot= 0;
930                 *item= eprop->itemf(C, ptr, free);
931
932                 if(totitem) {
933                         if(*item) {
934                                 for( ; (*item)[tot].identifier; tot++);
935                         }
936
937                         *totitem= tot;
938                 }
939         }
940         else {
941                 *item= eprop->item;
942                 if(totitem)
943                         *totitem= eprop->totitem;
944         }
945 }
946
947 int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
948 {       
949         EnumPropertyItem *item, *item_array;
950         int free;
951         
952         RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free);
953         
954         for(item= item_array; item->identifier; item++) {
955                 if(item->identifier[0] && strcmp(item->identifier, identifier)==0) {
956                         *value = item->value;
957                         break;
958                 }
959         }
960
961         if(free)
962                 MEM_freeN(item_array);
963
964         return (item->identifier) ? 1:0;
965 }
966
967 int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier)
968 {
969         for (; item->identifier; item++) {
970                 if(item->identifier[0] && item->value==value) {
971                         *identifier = item->identifier;
972                         return 1;
973                 }
974         }
975         return 0;
976 }
977
978 int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier)
979 {
980         int index= 0;
981         for (; item->identifier; item++) {
982                 if(item->identifier[0] && item->value & value) {
983                         identifier[index++] = item->identifier;
984                 }
985         }
986         identifier[index]= NULL;
987         return index;
988 }
989
990 int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name)
991 {
992         for (; item->identifier; item++) {
993                 if(item->identifier[0] && item->value==value) {
994                         *name = item->name;
995                         return 1;
996                 }
997         }
998         return 0;
999 }
1000
1001 int RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
1002 {       
1003         EnumPropertyItem *item= NULL;
1004         int result, free;
1005         
1006         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1007         if(item) {
1008                 result= RNA_enum_identifier(item, value, identifier);
1009                 if(free)
1010                         MEM_freeN(item);
1011
1012                 return result;
1013         }
1014         return 0;
1015 }
1016
1017 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier)
1018 {
1019         EnumPropertyItem *item= NULL;
1020         int result, free;
1021
1022         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1023         if(item) {
1024                 result= RNA_enum_bitflag_identifiers(item, value, identifier);
1025                 if(free)
1026                         MEM_freeN(item);
1027
1028                 return result;
1029         }
1030         return 0;
1031 }
1032
1033 const char *RNA_property_ui_name(PropertyRNA *prop)
1034 {
1035         return rna_ensure_property_name(prop);
1036 }
1037
1038 const char *RNA_property_ui_description(PropertyRNA *prop)
1039 {
1040         return rna_ensure_property_description(prop);
1041 }
1042
1043 int RNA_property_ui_icon(PropertyRNA *prop)
1044 {
1045         return rna_ensure_property(prop)->icon;
1046 }
1047
1048 int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1049 {
1050         ID *id;
1051         int flag;
1052
1053         prop= rna_ensure_property(prop);
1054
1055         if(prop->editable)
1056                 flag= prop->editable(ptr);
1057         else
1058                 flag= prop->flag;
1059         
1060         id= ptr->id.data;
1061
1062         return (flag & PROP_EDITABLE) && (!id || !id->lib || (flag & PROP_LIB_EXCEPTION));
1063 }
1064
1065 /* same as RNA_property_editable(), except this checks individual items in an array */
1066 int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1067 {
1068         ID *id;
1069         int flag;
1070
1071         prop= rna_ensure_property(prop);
1072         
1073         /* if there is no function to do this for a given index, 
1074          * just resort to doing this on the whole array
1075          */
1076         if (prop->itemeditable == NULL)
1077                 return RNA_property_editable(ptr, prop);
1078                 
1079         flag= prop->itemeditable(ptr, index);
1080         id= ptr->id.data;
1081         
1082         return (flag & PROP_EDITABLE) && (!id || !id->lib || (flag & PROP_LIB_EXCEPTION));
1083 }
1084
1085 int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1086 {
1087         int flag;
1088
1089         prop= rna_ensure_property(prop);
1090
1091         if(!(prop->flag & PROP_ANIMATEABLE))
1092                 return 0;
1093
1094         if(prop->editable)
1095                 flag= prop->editable(ptr);
1096         else
1097                 flag= prop->flag;
1098
1099         return (flag & PROP_EDITABLE);
1100 }
1101
1102 int RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
1103 {
1104         /* would need to ask animation system */
1105
1106         return 0;
1107 }
1108
1109 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1110 {
1111         int is_rna = (prop->magic == RNA_MAGIC);
1112         prop= rna_ensure_property(prop);
1113
1114         if(is_rna) {
1115                 if(prop->update) {
1116                         /* ideally no context would be needed for update, but there's some
1117                            parts of the code that need it still, so we have this exception */
1118                         if(prop->flag & PROP_CONTEXT_UPDATE) {
1119                                 if(C) ((ContextUpdateFunc)prop->update)(C, ptr);
1120                         }
1121                         else
1122                                 prop->update(bmain, scene, ptr);
1123                 }
1124                 if(prop->noteflag)
1125                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1126         }
1127         else {
1128                 /* WARNING! This is so property drivers update the display!
1129                  * not especially nice  */
1130                 DAG_id_flush_update(ptr->id.data, OB_RECALC_OB);
1131                 WM_main_add_notifier(NC_WINDOW, NULL);
1132         }
1133
1134 }
1135
1136 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1137 {
1138         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
1139 }
1140
1141 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1142 {
1143         rna_property_update(NULL, bmain, scene, ptr, prop);
1144 }
1145
1146 /* Property Data */
1147
1148 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
1149 {
1150         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1151         IDProperty *idprop;
1152
1153         if((idprop=rna_idproperty_check(&prop, ptr)))
1154                 return IDP_Int(idprop);
1155         else if(bprop->get)
1156                 return bprop->get(ptr);
1157         else
1158                 return bprop->defaultvalue;
1159 }
1160
1161 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1162 {
1163         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1164         IDProperty *idprop;
1165
1166         /* just incase other values are passed */
1167         if(value) value= 1;
1168
1169         if((idprop=rna_idproperty_check(&prop, ptr)))
1170                 IDP_Int(idprop)= value;
1171         else if(bprop->set)
1172                 bprop->set(ptr, value);
1173         else if(prop->flag & PROP_EDITABLE) {
1174                 IDPropertyTemplate val = {0};
1175                 IDProperty *group;
1176
1177                 val.i= value;
1178
1179                 group= RNA_struct_idproperties(ptr, 1);
1180                 if(group)
1181                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1182         }
1183 }
1184
1185 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1186 {
1187         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1188         IDProperty *idprop;
1189
1190         if((idprop=rna_idproperty_check(&prop, ptr))) {
1191                 if(prop->arraydimension == 0)
1192                         values[0]= RNA_property_boolean_get(ptr, prop);
1193                 else
1194                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
1195         }
1196         else if(prop->arraydimension == 0)
1197                 values[0]= RNA_property_boolean_get(ptr, prop);
1198         else if(bprop->getarray)
1199                 bprop->getarray(ptr, values);
1200         else if(bprop->defaultarray)
1201                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->totarraylength);
1202         else
1203                 memset(values, 0, sizeof(int)*prop->totarraylength);
1204 }
1205
1206 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1207 {
1208         int tmp[RNA_MAX_ARRAY_LENGTH];
1209         int len= rna_ensure_property_array_length(ptr, prop);
1210
1211         if(len <= RNA_MAX_ARRAY_LENGTH) {
1212                 RNA_property_boolean_get_array(ptr, prop, tmp);
1213                 return tmp[index];
1214         }
1215         else {
1216                 int *tmparray, value;
1217
1218                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_index");
1219                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1220                 value= tmparray[index];
1221                 MEM_freeN(tmparray);
1222
1223                 return value;
1224         }
1225 }
1226
1227 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1228 {
1229         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1230         IDProperty *idprop;
1231
1232         if((idprop=rna_idproperty_check(&prop, ptr))) {
1233                 if(prop->arraydimension == 0)
1234                         IDP_Int(idprop)= values[0];
1235                 else
1236                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1237         }
1238         else if(prop->arraydimension == 0)
1239                 RNA_property_boolean_set(ptr, prop, values[0]);
1240         else if(bprop->setarray)
1241                 bprop->setarray(ptr, values);
1242         else if(prop->flag & PROP_EDITABLE) {
1243                 IDPropertyTemplate val = {0};
1244                 IDProperty *group;
1245
1246                 val.array.len= prop->totarraylength;
1247                 val.array.type= IDP_INT;
1248
1249                 group= RNA_struct_idproperties(ptr, 1);
1250                 if(group) {
1251                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
1252                         IDP_AddToGroup(group, idprop);
1253                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1254                 }
1255         }
1256 }
1257
1258 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1259 {
1260         int tmp[RNA_MAX_ARRAY_LENGTH];
1261         int len= rna_ensure_property_array_length(ptr, prop);
1262
1263         if(len <= RNA_MAX_ARRAY_LENGTH) {
1264                 RNA_property_boolean_get_array(ptr, prop, tmp);
1265                 tmp[index]= value;
1266                 RNA_property_boolean_set_array(ptr, prop, tmp);
1267         }
1268         else {
1269                 int *tmparray;
1270
1271                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_index");
1272                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1273                 tmparray[index]= value;
1274                 RNA_property_boolean_set_array(ptr, prop, tmparray);
1275                 MEM_freeN(tmparray);
1276         }
1277 }
1278
1279 int RNA_property_boolean_get_default(PointerRNA *ptr, PropertyRNA *prop)
1280 {
1281         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1282         return bprop->defaultvalue;
1283 }
1284
1285 void RNA_property_boolean_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1286 {
1287         BooleanPropertyRNA *bprop= (BooleanPropertyRNA*)prop;
1288         
1289         if(prop->arraydimension == 0)
1290                 values[0]= bprop->defaultvalue;
1291         else if(bprop->defaultarray)
1292                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->totarraylength);
1293         else
1294                 memset(values, 0, sizeof(int)*prop->totarraylength);
1295 }
1296
1297 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1298 {
1299         int tmp[RNA_MAX_ARRAY_LENGTH];
1300         int len= rna_ensure_property_array_length(ptr, prop);
1301
1302         if(len <= RNA_MAX_ARRAY_LENGTH) {
1303                 RNA_property_boolean_get_default_array(ptr, prop, tmp);
1304                 return tmp[index];
1305         }
1306         else {
1307                 int *tmparray, value;
1308
1309                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_default_index");
1310                 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
1311                 value= tmparray[index];
1312                 MEM_freeN(tmparray);
1313
1314                 return value;
1315         }
1316 }
1317
1318 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
1319 {
1320         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1321         IDProperty *idprop;
1322
1323         if((idprop=rna_idproperty_check(&prop, ptr)))
1324                 return IDP_Int(idprop);
1325         else if(iprop->get)
1326                 return iprop->get(ptr);
1327         else
1328                 return iprop->defaultvalue;
1329 }
1330
1331 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1332 {
1333         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1334         IDProperty *idprop;
1335
1336         if((idprop=rna_idproperty_check(&prop, ptr)))
1337                 IDP_Int(idprop)= value;
1338         else if(iprop->set)
1339                 iprop->set(ptr, value);
1340         else if(prop->flag & PROP_EDITABLE) {
1341                 IDPropertyTemplate val = {0};
1342                 IDProperty *group;
1343
1344                 val.i= value;
1345
1346                 group= RNA_struct_idproperties(ptr, 1);
1347                 if(group)
1348                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1349         }
1350 }
1351
1352 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1353 {
1354         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1355         IDProperty *idprop;
1356
1357         if((idprop=rna_idproperty_check(&prop, ptr))) {
1358                 if(prop->arraydimension == 0)
1359                         values[0]= RNA_property_int_get(ptr, prop);
1360                 else
1361                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
1362         }
1363         else if(prop->arraydimension == 0)
1364                 values[0]= RNA_property_int_get(ptr, prop);
1365         else if(iprop->getarray)
1366                 iprop->getarray(ptr, values);
1367         else if(iprop->defaultarray)
1368                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->totarraylength);
1369         else
1370                 memset(values, 0, sizeof(int)*prop->totarraylength);
1371 }
1372
1373 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1374 {
1375         int tmp[RNA_MAX_ARRAY_LENGTH];
1376         int len= rna_ensure_property_array_length(ptr, prop);
1377
1378         if(len <= RNA_MAX_ARRAY_LENGTH) {
1379                 RNA_property_int_get_array(ptr, prop, tmp);
1380                 return tmp[index];
1381         }
1382         else {
1383                 int *tmparray, value;
1384
1385                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_int_get_index");
1386                 RNA_property_int_get_array(ptr, prop, tmparray);
1387                 value= tmparray[index];
1388                 MEM_freeN(tmparray);
1389
1390                 return value;
1391         }
1392 }
1393
1394 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1395 {
1396         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1397         IDProperty *idprop;
1398
1399         if((idprop=rna_idproperty_check(&prop, ptr))) {
1400                 if(prop->arraydimension == 0)
1401                         IDP_Int(idprop)= values[0];
1402                 else
1403                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);\
1404         }
1405         else if(prop->arraydimension == 0)
1406                 RNA_property_int_set(ptr, prop, values[0]);
1407         else if(iprop->setarray)
1408                 iprop->setarray(ptr, values);
1409         else if(prop->flag & PROP_EDITABLE) {
1410                 IDPropertyTemplate val = {0};
1411                 IDProperty *group;
1412
1413                 val.array.len= prop->totarraylength;
1414                 val.array.type= IDP_INT;
1415
1416                 group= RNA_struct_idproperties(ptr, 1);
1417                 if(group) {
1418                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
1419                         IDP_AddToGroup(group, idprop);
1420                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1421                 }
1422         }
1423 }
1424
1425 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1426 {
1427         int tmp[RNA_MAX_ARRAY_LENGTH];
1428         int len= rna_ensure_property_array_length(ptr, prop);
1429
1430         if(len <= RNA_MAX_ARRAY_LENGTH) {
1431                 RNA_property_int_get_array(ptr, prop, tmp);
1432                 tmp[index]= value;
1433                 RNA_property_int_set_array(ptr, prop, tmp);
1434         }
1435         else {
1436                 int *tmparray;
1437
1438                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_int_get_index");
1439                 RNA_property_int_get_array(ptr, prop, tmparray);
1440                 tmparray[index]= value;
1441                 RNA_property_int_set_array(ptr, prop, tmparray);
1442                 MEM_freeN(tmparray);
1443         }
1444 }
1445
1446 int RNA_property_int_get_default(PointerRNA *ptr, PropertyRNA *prop)
1447 {
1448         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1449         return iprop->defaultvalue;
1450 }
1451
1452 void RNA_property_int_get_default_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1453 {
1454         IntPropertyRNA *iprop= (IntPropertyRNA*)prop;
1455         
1456         if(prop->arraydimension == 0)
1457                 values[0]= iprop->defaultvalue;
1458         else if(iprop->defaultarray)
1459                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->totarraylength);
1460         else
1461                 memset(values, 0, sizeof(int)*prop->totarraylength);
1462 }
1463
1464 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1465 {
1466         int tmp[RNA_MAX_ARRAY_LENGTH];
1467         int len= rna_ensure_property_array_length(ptr, prop);
1468
1469         if(len <= RNA_MAX_ARRAY_LENGTH) {
1470                 RNA_property_int_get_default_array(ptr, prop, tmp);
1471                 return tmp[index];
1472         }
1473         else {
1474                 int *tmparray, value;
1475
1476                 tmparray= MEM_callocN(sizeof(int)*len, "RNA_property_int_get_default_index");
1477                 RNA_property_int_get_default_array(ptr, prop, tmparray);
1478                 value= tmparray[index];
1479                 MEM_freeN(tmparray);
1480
1481                 return value;
1482         }
1483 }
1484
1485 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
1486 {
1487         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1488         IDProperty *idprop;
1489
1490         if((idprop=rna_idproperty_check(&prop, ptr))) {
1491                 if(idprop->type == IDP_FLOAT)
1492                         return IDP_Float(idprop);
1493                 else
1494                         return (float)IDP_Double(idprop);
1495         }
1496         else if(fprop->get)
1497                 return fprop->get(ptr);
1498         else
1499                 return fprop->defaultvalue;
1500 }
1501
1502 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
1503 {
1504         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1505         IDProperty *idprop;
1506
1507         if((idprop=rna_idproperty_check(&prop, ptr))) {
1508                 if(idprop->type == IDP_FLOAT)
1509                         IDP_Float(idprop)= value;
1510                 else
1511                         IDP_Double(idprop)= value;
1512         }
1513         else if(fprop->set) {
1514                 fprop->set(ptr, value);
1515         }
1516         else if(prop->flag & PROP_EDITABLE) {
1517                 IDPropertyTemplate val = {0};
1518                 IDProperty *group;
1519
1520                 val.f= value;
1521
1522                 group= RNA_struct_idproperties(ptr, 1);
1523                 if(group)
1524                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, val, (char*)prop->identifier));
1525         }
1526 }
1527
1528 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
1529 {
1530         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1531         IDProperty *idprop;
1532         int i;
1533
1534         if((idprop=rna_idproperty_check(&prop, ptr))) {
1535                 if(prop->arraydimension == 0)
1536                         values[0]= RNA_property_float_get(ptr, prop);
1537                 else if(idprop->subtype == IDP_FLOAT) {
1538                         memcpy(values, IDP_Array(idprop), sizeof(float)*idprop->len);
1539                 }
1540                 else {
1541                         for(i=0; i<idprop->len; i++)
1542                                 values[i]=  (float)(((double*)IDP_Array(idprop))[i]);
1543                 }
1544         }
1545         else if(prop->arraydimension == 0)
1546                 values[0]= RNA_property_float_get(ptr, prop);
1547         else if(fprop->getarray)
1548                 fprop->getarray(ptr, values);
1549         else if(fprop->defaultarray)
1550                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->totarraylength);
1551         else
1552                 memset(values, 0, sizeof(float)*prop->totarraylength);
1553 }
1554
1555 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1556 {
1557         float tmp[RNA_MAX_ARRAY_LENGTH];
1558         int len= rna_ensure_property_array_length(ptr, prop);
1559
1560         if(len <= RNA_MAX_ARRAY_LENGTH) {
1561                 RNA_property_float_get_array(ptr, prop, tmp);
1562                 return tmp[index];
1563         }
1564         else {
1565                 float *tmparray, value;
1566
1567                 tmparray= MEM_callocN(sizeof(float)*len, "RNA_property_float_get_index");
1568                 RNA_property_float_get_array(ptr, prop, tmparray);
1569                 value= tmparray[index];
1570                 MEM_freeN(tmparray);
1571
1572                 return value;
1573         }
1574
1575 }
1576
1577 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
1578 {
1579         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1580         IDProperty *idprop;
1581         int i;
1582
1583         if((idprop=rna_idproperty_check(&prop, ptr))) {
1584                 if(prop->arraydimension == 0) {
1585                         if(idprop->type == IDP_FLOAT)
1586                                 IDP_Float(idprop)= values[0];
1587                         else
1588                                 IDP_Double(idprop)= values[0];
1589                 }
1590                 else if(idprop->subtype == IDP_FLOAT) {
1591                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
1592                 }
1593                 else {
1594                         for(i=0; i<idprop->len; i++)
1595                                 ((double*)IDP_Array(idprop))[i]= values[i];
1596                 }
1597         }
1598         else if(prop->arraydimension == 0)
1599                 RNA_property_float_set(ptr, prop, values[0]);
1600         else if(fprop->setarray) {
1601                 fprop->setarray(ptr, values);
1602         }
1603         else if(prop->flag & PROP_EDITABLE) {
1604                 IDPropertyTemplate val = {0};
1605                 IDProperty *group;
1606
1607                 val.array.len= prop->totarraylength;
1608                 val.array.type= IDP_FLOAT;
1609
1610                 group= RNA_struct_idproperties(ptr, 1);
1611                 if(group) {
1612                         idprop= IDP_New(IDP_ARRAY, val, (char*)prop->identifier);
1613                         IDP_AddToGroup(group, idprop);
1614                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
1615                 }
1616         }
1617 }
1618
1619 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
1620 {
1621         float tmp[RNA_MAX_ARRAY_LENGTH];
1622         int len= rna_ensure_property_array_length(ptr, prop);
1623
1624         if(len <= RNA_MAX_ARRAY_LENGTH) {
1625                 RNA_property_float_get_array(ptr, prop, tmp);
1626                 tmp[index]= value;
1627                 RNA_property_float_set_array(ptr, prop, tmp);
1628         }
1629         else {
1630                 float *tmparray;
1631
1632                 tmparray= MEM_callocN(sizeof(float)*len, "RNA_property_float_get_index");
1633                 RNA_property_float_get_array(ptr, prop, tmparray);
1634                 tmparray[index]= value;
1635                 RNA_property_float_set_array(ptr, prop, tmparray);
1636                 MEM_freeN(tmparray);
1637         }
1638 }
1639
1640 float RNA_property_float_get_default(PointerRNA *ptr, PropertyRNA *prop)
1641 {
1642         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1643         return fprop->defaultvalue;
1644 }
1645
1646 void RNA_property_float_get_default_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
1647 {
1648         FloatPropertyRNA *fprop= (FloatPropertyRNA*)prop;
1649         
1650         if(prop->arraydimension == 0)
1651                 values[0]= fprop->defaultvalue;
1652         else if(fprop->defaultarray)
1653                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->totarraylength);
1654         else
1655                 memset(values, 0, sizeof(float)*prop->totarraylength);
1656 }
1657
1658 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1659 {
1660         float tmp[RNA_MAX_ARRAY_LENGTH];
1661         int len= rna_ensure_property_array_length(ptr, prop);
1662
1663         if(len <= RNA_MAX_ARRAY_LENGTH) {
1664                 RNA_property_float_get_default_array(ptr, prop, tmp);
1665                 return tmp[index];
1666         }
1667         else {
1668                 float *tmparray, value;
1669
1670                 tmparray= MEM_callocN(sizeof(float)*len, "RNA_property_float_get_default_index");
1671                 RNA_property_float_get_default_array(ptr, prop, tmparray);
1672                 value= tmparray[index];
1673                 MEM_freeN(tmparray);
1674
1675                 return value;
1676         }
1677 }
1678
1679 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
1680 {
1681         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1682         IDProperty *idprop;
1683
1684         if((idprop=rna_idproperty_check(&prop, ptr)))
1685                 strcpy(value, IDP_String(idprop));
1686         else if(sprop->get)
1687                 sprop->get(ptr, value);
1688         else
1689                 strcpy(value, sprop->defaultvalue);
1690 }
1691
1692 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
1693 {
1694         char *buf;
1695         int length;
1696
1697         length= RNA_property_string_length(ptr, prop);
1698
1699         if(length+1 < fixedlen)
1700                 buf= fixedbuf;
1701         else
1702                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
1703
1704         RNA_property_string_get(ptr, prop, buf);
1705
1706         return buf;
1707 }
1708
1709 /* this is the length without \0 terminator */
1710 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
1711 {
1712         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1713         IDProperty *idprop;
1714
1715         if((idprop=rna_idproperty_check(&prop, ptr)))
1716                 return strlen(IDP_String(idprop));
1717         else if(sprop->length)
1718                 return sprop->length(ptr);
1719         else
1720                 return strlen(sprop->defaultvalue);
1721 }
1722
1723 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
1724 {
1725         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
1726         IDProperty *idprop;
1727
1728         if((idprop=rna_idproperty_check(&prop, ptr)))
1729                 IDP_AssignString(idprop, (char*)value);
1730         else if(sprop->set)
1731                 sprop->set(ptr, value);
1732         else if(prop->flag & PROP_EDITABLE) {
1733                 IDPropertyTemplate val = {0};
1734                 IDProperty *group;
1735
1736                 val.str= (char*)value;
1737
1738                 group= RNA_struct_idproperties(ptr, 1);
1739                 if(group)
1740                         IDP_AddToGroup(group, IDP_New(IDP_STRING, val, (char*)prop->identifier));
1741         }
1742 }
1743
1744 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
1745 {
1746         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1747         IDProperty *idprop;
1748
1749         if((idprop=rna_idproperty_check(&prop, ptr)))
1750                 return IDP_Int(idprop);
1751         else if(eprop->get)
1752                 return eprop->get(ptr);
1753         else
1754                 return eprop->defaultvalue;
1755 }
1756
1757 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1758 {
1759         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1760         IDProperty *idprop;
1761
1762         if((idprop=rna_idproperty_check(&prop, ptr)))
1763                 IDP_Int(idprop)= value;
1764         else if(eprop->set) {
1765                 eprop->set(ptr, value);
1766         }
1767         else if(prop->flag & PROP_EDITABLE) {
1768                 IDPropertyTemplate val = {0};
1769                 IDProperty *group;
1770
1771                 val.i= value;
1772
1773                 group= RNA_struct_idproperties(ptr, 1);
1774                 if(group)
1775                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, (char*)prop->identifier));
1776         }
1777 }
1778
1779 int RNA_property_enum_get_default(PointerRNA *ptr, PropertyRNA *prop)
1780 {
1781         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
1782         return eprop->defaultvalue;
1783 }
1784
1785
1786 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
1787 {
1788         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
1789         IDProperty *idprop;
1790
1791         if((idprop=rna_idproperty_check(&prop, ptr))) {
1792                 pprop= (PointerPropertyRNA*)prop;
1793
1794                 /* for groups, data is idprop itself */
1795                 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
1796         }
1797         else if(pprop->get) {
1798                 return pprop->get(ptr);
1799         }
1800         else if(prop->flag & PROP_IDPROPERTY) {
1801                 /* XXX temporary hack to add it automatically, reading should
1802                    never do any write ops, to ensure thread safety etc .. */
1803                 RNA_property_pointer_add(ptr, prop);
1804                 return RNA_property_pointer_get(ptr, prop);
1805         }
1806         else {
1807                 PointerRNA result;
1808
1809                 memset(&result, 0, sizeof(result));
1810                 return result;
1811         }
1812 }
1813
1814 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
1815 {
1816         IDProperty *idprop;
1817
1818         if((idprop=rna_idproperty_check(&prop, ptr))) {
1819                 /* not supported */
1820         }
1821         else {
1822                 PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
1823
1824                 if(pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL))
1825                         pprop->set(ptr, ptr_value);
1826         }
1827 }
1828
1829 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
1830 {
1831         IDProperty *idprop;
1832
1833         if((idprop=rna_idproperty_check(&prop, ptr))) {
1834                 /* already exists */
1835         }
1836         else if(prop->flag & PROP_IDPROPERTY) {
1837                 IDPropertyTemplate val = {0};
1838                 IDProperty *group;
1839
1840                 val.i= 0;
1841
1842                 group= RNA_struct_idproperties(ptr, 1);
1843                 if(group)
1844                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, val, (char*)prop->identifier));
1845         }
1846         else
1847                 printf("RNA_property_pointer_add %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
1848 }
1849
1850 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
1851 {
1852         IDProperty *idprop, *group;
1853
1854         if((idprop=rna_idproperty_check(&prop, ptr))) {
1855                 group= RNA_struct_idproperties(ptr, 0);
1856                 
1857                 if(group) {
1858                         IDP_RemFromGroup(group, idprop);
1859                         IDP_FreeProperty(idprop);
1860                         MEM_freeN(idprop);
1861                 }
1862         }
1863         else
1864                 printf("RNA_property_pointer_remove %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);
1865 }
1866
1867 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
1868 {
1869         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1870
1871         iter->ptr.data= rna_iterator_array_get(iter);
1872         iter->ptr.type= cprop->item_type;
1873         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
1874 }
1875
1876 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
1877 {
1878         IDProperty *idprop;
1879
1880         memset(iter, 0, sizeof(*iter));
1881
1882         if((idprop=rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
1883                 iter->parent= *ptr;
1884                 iter->prop= prop;
1885
1886                 if(idprop)
1887                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
1888                 else
1889                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
1890
1891                 if(iter->valid)
1892                         rna_property_collection_get_idp(iter);
1893
1894                 iter->idprop= 1;
1895         }
1896         else {
1897                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1898                 cprop->begin(iter, ptr);
1899         }
1900 }
1901
1902 void RNA_property_collection_next(CollectionPropertyIterator *iter)
1903 {
1904         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1905
1906         if(iter->idprop) {
1907                 rna_iterator_array_next(iter);
1908
1909                 if(iter->valid)
1910                         rna_property_collection_get_idp(iter);
1911         }
1912         else
1913                 cprop->next(iter);
1914 }
1915
1916 void RNA_property_collection_end(CollectionPropertyIterator *iter)
1917 {
1918         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
1919
1920         if(iter->idprop)
1921                 rna_iterator_array_end(iter);
1922         else
1923                 cprop->end(iter);
1924 }
1925
1926 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
1927 {
1928         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1929         IDProperty *idprop;
1930
1931         if((idprop=rna_idproperty_check(&prop, ptr))) {
1932                 return idprop->len;
1933         }
1934         else if(cprop->length) {
1935                 return cprop->length(ptr);
1936         }
1937         else {
1938                 CollectionPropertyIterator iter;
1939                 int length= 0;
1940
1941                 RNA_property_collection_begin(ptr, prop, &iter);
1942                 for(; iter.valid; RNA_property_collection_next(&iter))
1943                         length++;
1944                 RNA_property_collection_end(&iter);
1945
1946                 return length;
1947         }
1948 }
1949
1950 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
1951 {
1952         IDProperty *idprop;
1953 //      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1954
1955         if((idprop=rna_idproperty_check(&prop, ptr))) {
1956                 IDPropertyTemplate val = {0};
1957                 IDProperty *item;
1958
1959                 item= IDP_New(IDP_GROUP, val, "");
1960                 IDP_AppendArray(idprop, item);
1961                 IDP_FreeProperty(item);
1962                 MEM_freeN(item);
1963         }
1964         else if(prop->flag & PROP_IDPROPERTY) {
1965                 IDProperty *group, *item;
1966                 IDPropertyTemplate val = {0};
1967
1968                 group= RNA_struct_idproperties(ptr, 1);
1969                 if(group) {
1970                         idprop= IDP_NewIDPArray(prop->identifier);
1971                         IDP_AddToGroup(group, idprop);
1972
1973                         item= IDP_New(IDP_GROUP, val, "");
1974                         IDP_AppendArray(idprop, item);
1975                         IDP_FreeProperty(item);
1976                         MEM_freeN(item);
1977                 }
1978         }
1979
1980         /* py api calls directly */
1981 #if 0
1982         else if(cprop->add){
1983                 if(!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
1984                         ParameterList params;
1985                         RNA_parameter_list_create(&params, ptr, cprop->add);
1986                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
1987                         RNA_parameter_list_free(&params);
1988                 }
1989         }
1990         /*else
1991                 printf("RNA_property_collection_add %s.%s: not implemented for this property.\n", ptr->type->identifier, prop->identifier);*/
1992 #endif
1993
1994         if(r_ptr) {
1995                 if(idprop) {
1996                         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
1997
1998                         r_ptr->data= IDP_GetIndexArray(idprop, idprop->len-1);
1999                         r_ptr->type= cprop->item_type;
2000                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
2001                 }
2002                 else
2003                         memset(r_ptr, 0, sizeof(*r_ptr));
2004         }
2005 }
2006
2007 int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
2008 {
2009         IDProperty *idprop;
2010 //      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2011
2012         if((idprop=rna_idproperty_check(&prop, ptr))) {
2013                 IDProperty tmp, *array;
2014                 int len;
2015
2016                 len= idprop->len;
2017                 array= IDP_IDPArray(idprop);
2018
2019                 if(key >= 0 && key < len) {
2020                         if(key+1 < len) {
2021                                 /* move element to be removed to the back */
2022                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
2023                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(len-key+1));
2024                                 memcpy(&array[len-1], &tmp, sizeof(IDProperty));
2025                         }
2026
2027                         IDP_ResizeIDPArray(idprop, len-1);
2028                 }
2029
2030                 return 1;
2031         }
2032         else if(prop->flag & PROP_IDPROPERTY)
2033                 return 1;
2034
2035         /* py api calls directly */
2036 #if 0
2037         else if(cprop->remove){
2038                 if(!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2039                         ParameterList params;
2040                         RNA_parameter_list_create(&params, ptr, cprop->remove);
2041                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
2042                         RNA_parameter_list_free(&params);
2043                 }
2044
2045                 return 0;
2046         }
2047         /*else
2048                 printf("RNA_property_collection_remove %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);*/
2049 #endif
2050         return 0;
2051 }
2052
2053 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
2054 {
2055         IDProperty *idprop;
2056
2057         if((idprop=rna_idproperty_check(&prop, ptr)))
2058                 IDP_ResizeIDPArray(idprop, 0);
2059 }
2060
2061 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
2062 {
2063         CollectionPropertyIterator iter;
2064         int index= 0;
2065         
2066         RNA_property_collection_begin(ptr, prop, &iter);
2067         for(index=0; iter.valid; RNA_property_collection_next(&iter), index++) {
2068                 if (iter.ptr.data == t_ptr->data)
2069                         break;
2070         }
2071         RNA_property_collection_end(&iter);
2072         
2073         /* did we find it? */
2074         if (iter.valid)
2075                 return index;
2076         else
2077                 return -1;
2078 }
2079
2080 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
2081 {
2082         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2083
2084         if(cprop->lookupint) {
2085                 /* we have a callback defined, use it */
2086                 *r_ptr= cprop->lookupint(ptr, key);
2087                 return (r_ptr->data != NULL);
2088         }
2089         else {
2090                 /* no callback defined, just iterate and find the nth item */
2091                 CollectionPropertyIterator iter;
2092                 int i;
2093
2094                 RNA_property_collection_begin(ptr, prop, &iter);
2095                 for(i=0; iter.valid; RNA_property_collection_next(&iter), i++) {
2096                         if(i == key) {
2097                                 *r_ptr= iter.ptr;
2098                                 break;
2099                         }
2100                 }
2101                 RNA_property_collection_end(&iter);
2102
2103                 if(!iter.valid)
2104                         memset(r_ptr, 0, sizeof(*r_ptr));
2105
2106                 return iter.valid;
2107         }
2108 }
2109
2110 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
2111 {
2112         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2113
2114         if(cprop->lookupstring) {
2115                 /* we have a callback defined, use it */
2116                 *r_ptr= cprop->lookupstring(ptr, key);
2117                 return (r_ptr->data != NULL);
2118         }
2119         else {
2120                 /* no callback defined, compare with name properties if they exist */
2121                 CollectionPropertyIterator iter;
2122                 PropertyRNA *nameprop;
2123                 char name[256], *nameptr;
2124                 int found= 0;
2125
2126                 RNA_property_collection_begin(ptr, prop, &iter);
2127                 for(; iter.valid; RNA_property_collection_next(&iter)) {
2128                         if(iter.ptr.data && iter.ptr.type->nameproperty) {
2129                                 nameprop= iter.ptr.type->nameproperty;
2130
2131                                 nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name));
2132
2133                                 if(strcmp(nameptr, key) == 0) {
2134                                         *r_ptr= iter.ptr;
2135                                         found= 1;
2136                                 }
2137
2138                                 if((char *)&name != nameptr)
2139                                         MEM_freeN(nameptr);
2140
2141                                 if(found)
2142                                         break;
2143                         }
2144                 }
2145                 RNA_property_collection_end(&iter);
2146
2147                 if(!iter.valid)
2148                         memset(r_ptr, 0, sizeof(*r_ptr));
2149
2150                 return iter.valid;
2151         }
2152 }
2153
2154 int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2155 {
2156         *r_ptr= *ptr;
2157         return ((r_ptr->type = prop->srna) ? 1:0);
2158 }
2159
2160 int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
2161 {
2162         CollectionPropertyIterator iter;
2163         ArrayIterator *internal;
2164         char *arrayp;
2165
2166         if(!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
2167                 return 0;
2168
2169         RNA_property_collection_begin(ptr, prop, &iter);
2170
2171         if(iter.valid) {
2172                 /* get data from array iterator and item property */
2173                 internal= iter.internal;
2174                 arrayp= (iter.valid)? iter.ptr.data: NULL;
2175
2176                 if(internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
2177                         /* we might skip some items, so it's not a proper array */
2178                         RNA_property_collection_end(&iter);
2179                         return 0;
2180                 }
2181
2182                 array->array= arrayp + itemprop->rawoffset;
2183                 array->stride= internal->itemsize;
2184                 array->len= ((char*)internal->endptr - arrayp)/internal->itemsize;
2185                 array->type= itemprop->rawtype;
2186         }
2187         else
2188                 memset(array, 0, sizeof(RawArray));
2189
2190         RNA_property_collection_end(&iter);
2191
2192         return 1;
2193 }
2194
2195 #define RAW_GET(dtype, var, raw, a) \
2196 { \
2197         switch(raw.type) { \
2198                 case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break; \
2199                 case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break; \
2200                 case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break; \
2201                 case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break; \
2202                 case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break; \
2203                 default: var = (dtype)0; \
2204         } \
2205 }
2206
2207 #define RAW_SET(dtype, raw, a, var) \
2208 { \
2209         switch(raw.type) { \
2210                 case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break; \
2211                 case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break; \
2212                 case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break; \
2213                 case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break; \
2214                 case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break; \
2215         } \
2216 }
2217
2218 int RNA_raw_type_sizeof(RawPropertyType type)
2219 {
2220         switch(type) {
2221                 case PROP_RAW_CHAR: return sizeof(char);
2222                 case PROP_RAW_SHORT: return sizeof(short);
2223                 case PROP_RAW_INT: return sizeof(int);
2224                 case PROP_RAW_FLOAT: return sizeof(float);
2225                 case PROP_RAW_DOUBLE: return sizeof(double);
2226                 default: return 0;
2227         }
2228 }
2229
2230 static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
2231 {
2232         StructRNA *ptype;
2233         PointerRNA itemptr;
2234         PropertyRNA *itemprop, *iprop;
2235         PropertyType itemtype=0;
2236         RawArray in;
2237         int itemlen= 0;
2238
2239         /* initialize in array, stride assumed 0 in following code */
2240         in.array= inarray;
2241         in.type= intype;
2242         in.len= inlen;
2243         in.stride= 0;
2244
2245         ptype= RNA_property_pointer_type(ptr, prop);
2246
2247         /* try to get item property pointer */
2248         RNA_pointer_create(NULL, ptype, NULL, &itemptr);
2249         itemprop= RNA_struct_find_property(&itemptr, propname);
2250
2251         if(itemprop) {
2252                 /* we have item property pointer */
2253                 RawArray out;
2254
2255                 /* check type */
2256                 itemtype= RNA_property_type(itemprop);
2257
2258                 if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
2259                         BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
2260                         return 0;
2261                 }
2262
2263                 /* check item array */
2264                 itemlen= RNA_property_array_length(&itemptr, itemprop);
2265
2266                 /* try to access as raw array */
2267                 if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
2268                         if(in.len != itemlen*out.len) {
2269                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d).", out.len*itemlen, in.len);
2270                                 return 0;
2271                         }
2272                         
2273                         /* matching raw types */
2274                         if(out.type == in.type) {
2275                                 void *inp= in.array;
2276                                 void *outp= out.array;
2277                                 int a, size;
2278
2279                                 itemlen= (itemlen == 0)? 1: itemlen;
2280                                 size= RNA_raw_type_sizeof(out.type) * itemlen;
2281
2282                                 for(a=0; a<out.len; a++) {
2283                                         if(set) memcpy(outp, inp, size);
2284                                         else memcpy(inp, outp, size);
2285
2286                                         inp= (char*)inp + size;
2287                                         outp= (char*)outp + out.stride;
2288                                 }
2289
2290                                 return 1;
2291                         }
2292
2293                         /* could also be faster with non-matching types,
2294                          * for now we just do slower loop .. */
2295                 }
2296         }
2297
2298         {
2299                 void *tmparray= NULL;
2300                 int tmplen= 0;
2301                 int err= 0, j, a= 0;
2302
2303                 /* no item property pointer, can still be id property, or
2304                  * property of a type derived from the collection pointer type */
2305                 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2306                         if(itemptr.data) {
2307                                 if(itemprop) {
2308                                         /* we got the property already */
2309                                         iprop= itemprop;
2310                                 }
2311                                 else {
2312                                         /* not yet, look it up and verify if it is valid */
2313                                         iprop= RNA_struct_find_property(&itemptr, propname);
2314
2315                                         if(iprop) {
2316                                                 itemlen= RNA_property_array_length(&itemptr, iprop);
2317                                                 itemtype= RNA_property_type(iprop);
2318                                         }
2319                                         else {
2320                                                 BKE_reportf(reports, RPT_ERROR, "Property named %s not found.", propname);
2321                                                 err= 1;
2322                                                 break;
2323                                         }
2324
2325                                         if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
2326                                                 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported.");
2327                                                 err= 1;
2328                                                 break;
2329                                         }
2330                                 }
2331
2332                                 /* editable check */
2333                                 if(RNA_property_editable(&itemptr, iprop)) {
2334                                         if(a+itemlen > in.len) {
2335                                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more).", in.len);
2336                                                 err= 1;
2337                                                 break;
2338                                         }
2339
2340                                         if(itemlen == 0) {
2341                                                 /* handle conversions */
2342                                                 if(set) {
2343                                                         switch(itemtype) {
2344                                                                 case PROP_BOOLEAN: {
2345                                                                         int b;
2346                                                                         RAW_GET(int, b, in, a);
2347                                                                         RNA_property_boolean_set(&itemptr, iprop, b);
2348                                                                         break;
2349                                                                 }
2350                                                                 case PROP_INT: {
2351                                                                         int i;
2352                                                                         RAW_GET(int, i, in, a);
2353                                                                         RNA_property_int_set(&itemptr, iprop, i);
2354                                                                         break;
2355                                                                 }
2356                                                                 case PROP_FLOAT: {
2357                                                                         float f;
2358                                                                         RAW_GET(float, f, in, a);
2359                                                                         RNA_property_float_set(&itemptr, iprop, f);
2360                                                                         break;
2361                                                                 }
2362                                                                 default:
2363                                                                         break;
2364                                                         }
2365                                                 }
2366                                                 else {
2367                                                         switch(itemtype) {
2368                                                                 case PROP_BOOLEAN: {
2369                                                                         int b= RNA_property_boolean_get(&itemptr, iprop);
2370                                                                         RAW_SET(int, in, a, b);
2371                                                                         break;
2372                                                                 }
2373                                                                 case PROP_INT: {
2374                                                                         int i= RNA_property_int_get(&itemptr, iprop);
2375                                                                         RAW_SET(int, in, a, i);
2376                                                                         break;
2377                                                                 }
2378                                                                 case PROP_FLOAT: {
2379                                                                         float f= RNA_property_float_get(&itemptr, iprop);
2380                                                                         RAW_SET(float, in, a, f);
2381                                                                         break;
2382                                                                 }
2383                                                                 default:
2384                                                                         break;
2385                                                         }
2386                                                 }
2387                                                 a++;
2388                                         }
2389                                         else {
2390                                                 /* allocate temporary array if needed */
2391                                                 if(tmparray && tmplen != itemlen) {
2392                                                         MEM_freeN(tmparray);
2393                                                         tmparray= NULL;
2394                                                 }
2395                                                 if(!tmparray) {
2396                                                         tmparray= MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n");
2397                                                         tmplen= itemlen;
2398                                                 }
2399
2400                                                 /* handle conversions */
2401                                                 if(set) {
2402                                                         switch(itemtype) {
2403                                                                 case PROP_BOOLEAN: {
2404                                                                         for(j=0; j<itemlen; j++, a++)
2405                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
2406                                                                         RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
2407                                                                         break;
2408                                                                 }
2409                                                                 case PROP_INT: {
2410                                                                         for(j=0; j<itemlen; j++, a++)
2411                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
2412                                                                         RNA_property_int_set_array(&itemptr, iprop, tmparray);
2413                                                                         break;
2414                                                                 }
2415                                                                 case PROP_FLOAT: {
2416                                                                         for(j=0; j<itemlen; j++, a++)
2417                                                                                 RAW_GET(float, ((float*)tmparray)[j], in, a);
2418                                                                         RNA_property_float_set_array(&itemptr, iprop, tmparray);
2419                                                                         break;
2420                                                                 }
2421                                                                 default:
2422                                                                         break;
2423                                                         }
2424                                                 }
2425                                                 else {
2426                                                         switch(itemtype) {
2427                                                                 case PROP_BOOLEAN: {
2428                                                                         RNA_property_boolean_get_array(&itemptr, iprop, tmparray);
2429                                                                         for(j=0; j<itemlen; j++, a++)
2430                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
2431                                                                         break;
2432                                                                 }
2433                                                                 case PROP_INT: {
2434                                                                         RNA_property_int_get_array(&itemptr, iprop, tmparray);
2435                                                                         for(j=0; j<itemlen; j++, a++)
2436                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
2437                                                                         break;
2438                                                                 }
2439                                                                 case PROP_FLOAT: {
2440                                                                         RNA_property_float_get_array(&itemptr, iprop, tmparray);
2441                                                                         for(j=0; j<itemlen; j++, a++)
2442                                                                                 RAW_SET(float, in, a, ((float*)tmparray)[j]);
2443                                                                         break;
2444                                                                 }
2445                                                                 default:
2446                                                                         break;
2447                                                         }
2448                                                 }
2449                                         }
2450                                 }
2451                         }
2452                 }
2453                 RNA_PROP_END;
2454
2455                 if(tmparray)
2456                         MEM_freeN(tmparray);
2457
2458                 return !err;
2459         }
2460 }
2461
2462 RawPropertyType RNA_property_raw_type(PropertyRNA *prop)
2463 {
2464         return prop->rawtype;
2465 }
2466
2467 int RNA_property_collection_raw_get(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
2468 {
2469         return rna_raw_access(reports, ptr, prop, propname, array, type, len, 0);
2470 }
2471
2472 int RNA_property_collection_raw_set(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, char *propname, void *array, RawPropertyType type, int len)
2473 {
2474         return rna_raw_access(reports, ptr, prop, propname, array, type, len, 1);
2475 }
2476
2477 /* Standard iterator functions */
2478
2479 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb, IteratorSkipFunc skip)
2480 {
2481         ListBaseIterator *internal;
2482
2483         internal= MEM_callocN(sizeof(ListBaseIterator), "ListBaseIterator");
2484         internal->link= (lb)? lb->first: NULL;
2485         internal->skip= skip;
2486
2487         iter->internal= internal;
2488         iter->valid= (internal->link != NULL);
2489
2490         if(skip && iter->valid && skip(iter, internal->link))
2491                 rna_iterator_listbase_next(iter);
2492 }
2493
2494 void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
2495 {
2496         ListBaseIterator *internal= iter->internal;
2497
2498         if(internal->skip) {
2499                 do {
2500                         internal->link= internal->link->next;
2501                         iter->valid= (internal->link != NULL);
2502                 } while(iter->valid && internal->skip(iter, internal->link));
2503         }
2504         else {
2505                 internal->link= internal->link->next;
2506                 iter->valid= (internal->link != NULL);
2507         }
2508 }
2509
2510 void *rna_iterator_listbase_get(CollectionPropertyIterator *iter)
2511 {
2512         ListBaseIterator *internal= iter->internal;
2513
2514         return internal->link;
2515 }
2516
2517 void rna_iterator_listbase_end(CollectionPropertyIterator *iter)
2518 {
2519         MEM_freeN(iter->internal);
2520         iter->internal= NULL;
2521 }
2522
2523 void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int itemsize, int length, int free_ptr, IteratorSkipFunc skip)
2524 {
2525         ArrayIterator *internal;
2526
2527         if(ptr == NULL)
2528                 length= 0;
2529
2530         internal= MEM_callocN(sizeof(ArrayIterator), "ArrayIterator");
2531         internal->ptr= ptr;
2532         internal->free_ptr= free_ptr ? ptr:NULL;
2533         internal->endptr= ((char*)ptr)+length*itemsize;
2534         internal->itemsize= itemsize;
2535         internal->skip= skip;
2536
2537         iter->internal= internal;
2538         iter->valid= (internal->ptr != internal->endptr);
2539
2540         if(skip && iter->valid && skip(iter, internal->ptr))
2541                 rna_iterator_array_next(iter);
2542 }
2543
2544 void rna_iterator_array_next(CollectionPropertyIterator *iter)
2545 {
2546         ArrayIterator *internal= iter->internal;
2547
2548         if(internal->skip) {
2549                 do {
2550                         internal->ptr += internal->itemsize;
2551                         iter->valid= (internal->ptr != internal->endptr);
2552                 } while(iter->valid && internal->skip(iter, internal->ptr));
2553         }
2554         else {
2555                 internal->ptr += internal->itemsize;
2556                 iter->valid= (internal->ptr != internal->endptr);
2557         }
2558 }
2559
2560 void *rna_iterator_array_get(CollectionPropertyIterator *iter)
2561 {
2562         ArrayIterator *internal= iter->internal;
2563
2564         return internal->ptr;
2565 }
2566
2567 void *rna_iterator_array_dereference_get(CollectionPropertyIterator *iter)
2568 {
2569         ArrayIterator *internal= iter->internal;
2570
2571         /* for ** arrays */
2572         return *(void**)(internal->ptr);
2573 }
2574
2575 void rna_iterator_array_end(CollectionPropertyIterator *iter)
2576 {
2577         ArrayIterator *internal= iter->internal;
2578         
2579         if(internal->free_ptr) {
2580                 MEM_freeN(internal->free_ptr);
2581                 internal->free_ptr= NULL;
2582         }
2583         MEM_freeN(iter->internal);
2584         iter->internal= NULL;
2585 }
2586
2587 /* RNA Path - Experiment */
2588
2589 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
2590 {
2591         const char *p;
2592         char *buf;
2593         int i, j, len, escape;
2594
2595         len= 0;
2596
2597         if(bracket) {
2598                 /* get data between [], check escaping ] with \] */
2599                 if(**path == '[') (*path)++;
2600                 else return NULL;
2601
2602                 p= *path;
2603
2604                 escape= 0;
2605                 while(*p && (*p != ']' || escape)) {
2606                         escape= (*p == '\\');
2607                         len++;
2608                         p++;
2609                 }
2610
2611                 if(*p != ']') return NULL;
2612         }
2613         else {
2614                 /* get data until . or [ */
2615                 p= *path;
2616
2617                 while(*p && *p != '.' && *p != '[') {
2618                         len++;
2619                         p++;
2620                 }
2621         }
2622         
2623         /* empty, return */
2624         if(len == 0)
2625                 return NULL;
2626         
2627         /* try to use fixed buffer if possible */
2628         if(len+1 < fixedlen)
2629                 buf= fixedbuf;
2630         else
2631                 buf= MEM_callocN(sizeof(char)*(len+1), "rna_path_token");
2632
2633         /* copy string, taking into account escaped ] */
2634         if(bracket) {
2635                 for(p=*path, i=0, j=0; i<len; i++, p++) {
2636                         if(*p == '\\' && *(p+1) == ']');
2637                         else buf[j++]= *p;
2638                 }
2639
2640                 buf[j]= 0;
2641         }
2642         else {
2643                 memcpy(buf, *path, sizeof(char)*len);
2644                 buf[len]= '\0';
2645         }
2646
2647         /* set path to start of next token */
2648         if(*p == ']') p++;
2649         if(*p == '.') p++;
2650         *path= p;
2651
2652         return buf;
2653 }
2654
2655 static int rna_token_strip_quotes(char *token)
2656 {
2657         if(token[0]=='"') {
2658                 int len = strlen(token);
2659                 if (len >= 2 && token[len-1]=='"') {
2660                         /* strip away "" */
2661                         token[len-1]= '\0';
2662                         return 1;
2663                 }
2664         }
2665         return 0;
2666 }
2667
2668 /* Resolve the given RNA path to find the pointer+property indicated at the end of the path */
2669 int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
2670 {
2671         return RNA_path_resolve_full(ptr, path, r_ptr, r_prop, NULL);
2672 }
2673
2674 int RNA_path_resolve_full(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *index)
2675 {
2676         PropertyRNA *prop;
2677         PointerRNA curptr, nextptr;
2678         char fixedbuf[256], *token;
2679         int type, len, intkey;
2680
2681         prop= NULL;
2682         curptr= *ptr;
2683
2684         if(path==NULL || *path=='\0')
2685                 return 0;
2686
2687         while(*path) {
2688                 int use_id_prop = (*path=='[') ? 1:0;
2689                 /* custom property lookup ?
2690                  * C.object["someprop"]
2691                  */
2692
2693                 /* look up property name in current struct */
2694                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), use_id_prop);
2695
2696                 if(!token)
2697                         return 0;
2698
2699                 if(use_id_prop) { /* look up property name in current struct */
2700                         IDProperty *group= RNA_struct_idproperties(&curptr, 0);
2701                         if(group && rna_token_strip_quotes(token))
2702                                 prop= (PropertyRNA *)IDP_GetPropertyFromGroup(group, token+1);
2703                 }
2704                 else {
2705                         prop= RNA_struct_find_property(&curptr, token);
2706                 }
2707
2708                 if(token != fixedbuf)
2709                         MEM_freeN(token);
2710
2711                 if(!prop)
2712                         return 0;
2713
2714                 type= RNA_property_type(prop);
2715
2716                 /* now look up the value of this property if it is a pointer or
2717                  * collection, otherwise return the property rna so that the
2718                  * caller can read the value of the property itself */
2719                 switch (type) {
2720                 case PROP_POINTER:
2721                         nextptr= RNA_property_pointer_get(&curptr, prop);
2722
2723                         if(nextptr.data)
2724                                 curptr= nextptr;
2725                         else
2726                                 return 0;
2727
2728                         break;
2729                 case PROP_COLLECTION:
2730                         if(*path) {
2731                                 /* resolve the lookup with [] brackets */
2732                                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
2733
2734                                 if(!token)
2735                                         return 0;
2736
2737                                 len= strlen(token);
2738
2739                                 /* check for "" to see if it is a string */
2740                                 if(rna_token_strip_quotes(token)) {
2741                                         RNA_property_collection_lookup_string(&curptr, prop, token+1, &nextptr);
2742                                 }
2743                                 else {
2744                                         /* otherwise do int lookup */
2745                                         intkey= atoi(token);
2746                                         RNA_property_collection_lookup_int(&curptr, prop, intkey, &nextptr);
2747                                 }
2748
2749                                 if(token != fixedbuf)
2750                                         MEM_freeN(token);
2751
2752                                 if(nextptr.data)
2753                                         curptr= nextptr;
2754                                 else
2755                                         return 0;
2756                         }
2757
2758                         break;
2759                 default:
2760                         if (index==NULL)
2761                                 break;
2762
2763                         *index= -1;
2764
2765                         if (*path) {
2766                                 if (*path=='[') {
2767                                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
2768
2769                                         /* check for "" to see if it is a string */
2770                                         if(rna_token_strip_quotes(token)) {
2771                                                 *index= RNA_property_array_item_index(prop, *(token+1));
2772                                         }
2773                                         else {
2774                                                 /* otherwise do int lookup */
2775                                                 *index= atoi(token);
2776                                         }
2777                                 }
2778                                 else {
2779                                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 0);
2780                                         *index= RNA_property_array_item_index(prop, *token);
2781                                 }
2782
2783                                 if(token != fixedbuf)
2784                                         MEM_freeN(token);
2785                         }
2786                 }
2787         }
2788
2789         *r_ptr= curptr;
2790         *r_prop= prop;
2791
2792         return 1;
2793 }
2794
2795
2796 char *RNA_path_append(const char *path, PointerRNA *ptr, PropertyRNA *prop, int intkey, const char *strkey)
2797 {
2798         DynStr *dynstr;
2799         const char *s;
2800         char appendstr[128], *result;
2801         
2802         dynstr= BLI_dynstr_new();
2803
2804         /* add .identifier */
2805         if(path) {
2806                 BLI_dynstr_append(dynstr, (char*)path);
2807                 if(*path)
2808                         BLI_dynstr_append(dynstr, ".");
2809         }
2810
2811         BLI_dynstr_append(dynstr, (char*)RNA_property_identifier(prop));
2812
2813         if(RNA_property_type(prop) == PROP_COLLECTION) {
2814                 /* add ["strkey"] or [intkey] */
2815                 BLI_dynstr_append(dynstr, "[");
2816
2817                 if(strkey) {
2818                         BLI_dynstr_append(dynstr, "\"");
2819                         for(s=strkey; *s; s++) {
2820                                 if(*s == '[') {
2821                                         appendstr[0]= '\\';
2822                                         appendstr[1]= *s;
2823                                         appendstr[2]= 0;
2824                                 }
2825                                 else {
2826                                         appendstr[0]= *s;
2827                                         appendstr[1]= 0;
2828                                 }
2829                                 BLI_dynstr_append(dynstr, appendstr);
2830                         }
2831                         BLI_dynstr_append(dynstr, "\"");
2832                 }
2833                 else {
2834                         sprintf(appendstr, "%d", intkey);
2835                         BLI_dynstr_append(dynstr, appendstr);
2836                 }
2837
2838                 BLI_dynstr_append(dynstr, "]");
2839         }
2840
2841         result= BLI_dynstr_get_cstring(dynstr);
2842         BLI_dynstr_free(dynstr);
2843
2844         return result;
2845 }
2846
2847 char *RNA_path_back(const char *path)
2848 {
2849         char fixedbuf[256];
2850         const char *previous, *current;
2851         char *result, *token;
2852         int i;
2853
2854         if(!path)
2855                 return NULL;
2856
2857         previous= NULL;
2858         current= path;
2859
2860         /* parse token by token until the end, then we back up to the previous
2861          * position and strip of the next token to get the path one step back */
2862         while(*current) {
2863                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 0);
2864
2865                 if(!token)
2866                         return NULL;
2867                 if(token != fixedbuf)
2868                         MEM_freeN(token);
2869
2870                 /* in case of collection we also need to strip off [] */
2871                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 1);
2872                 if(token && token != fixedbuf)
2873                         MEM_freeN(token);
2874                 
2875                 if(!*current)
2876                         break;
2877
2878                 previous= current;
2879         }
2880
2881         if(!previous)
2882                 return NULL;
2883
2884         /* copy and strip off last token */
2885         i= previous - path;
2886         result= BLI_strdup(path);
2887
2888         if(i > 0 && result[i-1] == '.') i--;
2889         result[i]= 0;
2890
2891         return result;
2892 }
2893
2894 char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
2895 {
2896         char *ptrpath=NULL;
2897
2898         if(!ptr->id.data || !ptr->data)
2899                 return NULL;
2900         
2901         if(!RNA_struct_is_ID(ptr->type)) {
2902                 if(ptr->type->path) {
2903                         /* if type has a path to some ID, use it */
2904                         ptrpath= ptr->type->path(ptr);
2905                 }
2906                 else if(ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) {
2907                         PointerRNA parentptr;
2908                         PropertyRNA *userprop;
2909                         
2910                         /* find the property in the struct we're nested in that references this struct, and 
2911                          * use its identifier as the first part of the path used...
2912                          */
2913                         RNA_id_pointer_create(ptr->id.data, &parentptr);
2914                         userprop= RNA_struct_find_nested(&parentptr, ptr->type); 
2915                         
2916                         if(userprop)
2917                                 ptrpath= BLI_strdup(RNA_property_identifier(userprop));
2918                         else
2919                                 return NULL; // can't do anything about this case yet...
2920                 }
2921                 else
2922                         return NULL;
2923         }
2924         
2925         return ptrpath;
2926 }
2927
2928 char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
2929 {
2930         int is_rna = (prop->magic == RNA_MAGIC);
2931         const char *propname;
2932         char *ptrpath, *path;
2933
2934         if(!ptr->id.data || !ptr->data || !prop)
2935                 return NULL;
2936         
2937         /* path from ID to the struct holding this property */
2938         ptrpath= RNA_path_from_ID_to_struct(ptr);
2939
2940         propname= RNA_property_identifier(prop);
2941
2942         if(ptrpath) {
2943                 path= BLI_sprintfN(is_rna ? "%s.%s":"%s[\"%s\"]", ptrpath, propname);
2944                 MEM_freeN(ptrpath);
2945         }
2946         else {
2947                 if(is_rna)
2948                         path= BLI_strdup(propname);
2949                 else
2950                         path= BLI_sprintfN("[\"%s\"]", propname);
2951         }
2952
2953         return path;
2954 }
2955
2956 /* Quick name based property access */
2957
2958 int RNA_boolean_get(PointerRNA *ptr, const char *name)
2959 {
2960         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
2961
2962         if(prop) {
2963                 return RNA_property_boolean_get(ptr, prop);
2964         }
2965         else {
2966                 printf("RNA_boolean_get: %s.%s not found.\n", ptr->type->identifier, name);
2967                 return 0;
2968         }
2969 }
2970
2971 void RNA_boolean_set(PointerRNA *ptr, const char *name, int value)
2972 {
2973         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
2974
2975         if(prop)
2976                 RNA_property_boolean_set(ptr, prop, value);
2977         else
2978                 printf("RNA_boolean_set: %s.%s not found.\n", ptr->type->identifier, name);
2979 }
2980
2981 void RNA_boolean_get_array(PointerRNA *ptr, const char *name, int *values)
2982 {
2983         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
2984
2985         if(prop)
2986                 RNA_property_boolean_get_array(ptr, prop, values);
2987         else
2988                 printf("RNA_boolean_get_array: %s.%s not found.\n", ptr->type->identifier, name);
2989 }
2990
2991 void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const int *values)
2992 {
2993         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
2994
2995         if(prop)
2996                 RNA_property_boolean_set_array(ptr, prop, values);
2997         else
2998                 printf("RNA_boolean_set_array: %s.%s not found.\n", ptr->type->identifier, name);
2999 }
3000
3001 int RNA_int_get(PointerRNA *ptr, const char *name)
3002 {
3003         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3004
3005         if(prop) {
3006                 return RNA_property_int_get(ptr, prop);
3007         }
3008         else {
3009                 printf("RNA_int_get: %s.%s not found.\n", ptr->type->identifier, name);
3010                 return 0;
3011         }
3012 }
3013
3014 void RNA_int_set(PointerRNA *ptr, const char *name, int value)
3015 {
3016         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3017
3018         if(prop)
3019                 RNA_property_int_set(ptr, prop, value);
3020         else
3021                 printf("RNA_int_set: %s.%s not found.\n", ptr->type->identifier, name);
3022 }
3023
3024 void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
3025 {
3026         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3027
3028         if(prop)
3029                 RNA_property_int_get_array(ptr, prop, values);
3030         else
3031                 printf("RNA_int_get_array: %s.%s not found.\n", ptr->type->identifier, name);
3032 }
3033
3034 void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
3035 {
3036         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3037
3038         if(prop)
3039                 RNA_property_int_set_array(ptr, prop, values);
3040         else
3041                 printf("RNA_int_set_array: %s.%s not found.\n", ptr->type->identifier, name);
3042 }
3043
3044 float RNA_float_get(PointerRNA *ptr, const char *name)
3045 {
3046         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3047
3048         if(prop) {
3049                 return RNA_property_float_get(ptr, prop);
3050         }
3051         else {
3052                 printf("RNA_float_get: %s.%s not found.\n", ptr->type->identifier, name);
3053                 return 0;
3054         }
3055 }
3056
3057 void RNA_float_set(PointerRNA *ptr, const char *name, float value)
3058 {
3059         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3060
3061         if(prop)
3062                 RNA_property_float_set(ptr, prop, value);
3063         else
3064                 printf("RNA_float_set: %s.%s not found.\n", ptr->type->identifier, name);
3065 }
3066
3067 void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
3068 {
3069         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3070
3071         if(prop)
3072                 RNA_property_float_get_array(ptr, prop, values);
3073         else
3074                 printf("RNA_float_get_array: %s.%s not found.\n", ptr->type->identifier, name);
3075 }
3076
3077 void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
3078 {
3079         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3080
3081         if(prop)
3082                 RNA_property_float_set_array(ptr, prop, values);
3083         else
3084                 printf("RNA_float_set_array: %s.%s not found.\n", ptr->type->identifier, name);
3085 }
3086
3087 int RNA_enum_get(PointerRNA *ptr, const char *name)
3088 {
3089         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3090
3091         if(prop) {
3092                 return RNA_property_enum_get(ptr, prop);
3093         }
3094         else {
3095                 printf("RNA_enum_get: %s.%s not found.\n", ptr->type->identifier, name);
3096                 return 0;
3097         }
3098 }
3099
3100 void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
3101 {
3102         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3103
3104         if(prop)
3105                 RNA_property_enum_set(ptr, prop, value);
3106         else
3107                 printf("RNA_enum_set: %s.%s not found.\n", ptr->type->identifier, name);
3108 }
3109
3110 int RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname)
3111 {
3112         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3113         EnumPropertyItem *item;
3114         int free;
3115
3116         if(prop) {
3117                 RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
3118
3119                 for(; item->identifier; item++)
3120                         if(strcmp(item->identifier, enumname) == 0)
3121                                 return (item->value == RNA_property_enum_get(ptr, prop));
3122
3123                 if(free)
3124                         MEM_freeN(item);
3125
3126                 printf("RNA_enum_is_equal: %s.%s item %s not found.\n", ptr->type->identifier, name, enumname);
3127                 return 0;
3128         }
3129         else {
3130                 printf("RNA_enum_is_equal: %s.%s not found.\n", ptr->type->identifier, name);
3131                 return 0;
3132         }
3133 }
3134
3135 int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value)
3136 {
3137         for( ; item->identifier; item++) {
3138                 if(strcmp(item->identifier, identifier)==0) {
3139                         *value= item->value;
3140                         return 1;
3141                 }
3142         }
3143         
3144         return 0;
3145 }
3146
3147 int     RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier)
3148 {
3149         for( ; item->identifier; item++) {
3150                 if(item->value==value) {
3151                         *identifier= item->identifier;
3152                         return 1;
3153                 }
3154         }
3155
3156         return 0;
3157 }
3158
3159 void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
3160 {
3161         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3162
3163         if(prop)
3164                 RNA_property_string_get(ptr, prop, value);
3165         else
3166                 printf("RNA_string_get: %s.%s not found.\n", ptr->type->identifier, name);
3167 }
3168
3169 char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen)
3170 {
3171         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3172
3173         if(prop) {
3174                 return RNA_property_string_get_alloc(ptr, prop, fixedbuf, fixedlen);
3175         }
3176         else {
3177                 printf("RNA_string_get_alloc: %s.%s not found.\n", ptr->type->identifier, name);
3178                 return 0;
3179         }
3180 }
3181
3182 int RNA_string_length(PointerRNA *ptr, const char *name)
3183 {
3184         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3185
3186         if(prop) {
3187                 return RNA_property_string_length(ptr, prop);
3188         }
3189         else {
3190                 printf("RNA_string_length: %s.%s not found.\n", ptr->type->identifier, name);
3191                 return 0;
3192         }
3193 }
3194
3195 void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
3196 {
3197         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3198
3199         if(prop)
3200                 RNA_property_string_set(ptr, prop, value);
3201         else
3202                 printf("RNA_string_set: %s.%s not found.\n", ptr->type->identifier, name);
3203 }
3204
3205 PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
3206 {
3207         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3208
3209         if(prop) {
3210                 return RNA_property_pointer_get(ptr, prop);
3211         }
3212         else {
3213                 PointerRNA result;
3214
3215                 printf("RNA_pointer_get: %s.%s not found.\n", ptr->type->identifier, name);
3216
3217                 memset(&result, 0, sizeof(result));
3218                 return result;
3219         }
3220 }
3221
3222 void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value)
3223 {
3224         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3225
3226         if(prop) {
3227                 RNA_property_pointer_set(ptr, prop, ptr_value);
3228         }
3229         else {
3230                 printf("RNA_pointer_set: %s.%s not found.\n", ptr->type->identifier, name);
3231         }
3232 }
3233
3234 void RNA_pointer_add(PointerRNA *ptr, const char *name)
3235 {
3236         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3237
3238         if(prop)
3239                 RNA_property_pointer_add(ptr, prop);
3240         else
3241                 printf("RNA_pointer_set: %s.%s not found.\n", ptr->type->identifier, name);
3242 }
3243
3244 void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter)
3245 {
3246         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3247
3248         if(prop)
3249                 RNA_property_collection_begin(ptr, prop, iter);
3250         else
3251                 printf("RNA_collection_begin: %s.%s not found.\n", ptr->type->identifier, name);
3252 }
3253
3254 void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value)
3255 {
3256         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3257
3258         if(prop)
3259                 RNA_property_collection_add(ptr, prop, r_value);
3260         else
3261                 printf("RNA_collection_add: %s.%s not found.\n", ptr->type->identifier, name);
3262 }
3263
3264 void RNA_collection_clear(PointerRNA *ptr, const char *name)
3265 {
3266         PropertyRNA *prop= RNA_struct_find_property(ptr, name);
3267
3268         if(prop)
3269                 RNA_property_collection_clear(ptr, prop);
3270         else
3271                 printf("RNA_collection_clear: %s.%s not found.\n", ptr->type->identifier, name);
3272 }
3273