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