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