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