Merging r41176 through r41192 from trunk into soc-2011-tomato
[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, int *r_len)
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, r_len);
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, 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, 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, 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, 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, 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, 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,
2280                                     char *fixedbuf, int fixedlen, int *r_len)
2281 {
2282         char *buf;
2283         int length;
2284
2285         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2286
2287         length= RNA_property_string_length(ptr, prop);
2288
2289         if(length+1 < fixedlen)
2290                 buf= fixedbuf;
2291         else
2292                 buf= MEM_mallocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
2293
2294 #ifndef NDEBUG
2295         /* safety check to ensure the string is actually set */
2296         buf[length]= 255;
2297 #endif
2298
2299         RNA_property_string_get(ptr, prop, buf);
2300
2301 #ifndef NDEBUG
2302         BLI_assert(buf[length] == '\0');
2303 #endif
2304
2305         if (r_len) {
2306                 *r_len= length;
2307         }
2308
2309         return buf;
2310 }
2311
2312 /* this is the length without \0 terminator */
2313 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
2314 {
2315         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
2316         IDProperty *idprop;
2317
2318         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2319
2320         if((idprop=rna_idproperty_check(&prop, ptr)))
2321                 return strlen(IDP_String(idprop));
2322         else if(sprop->length)
2323                 return sprop->length(ptr);
2324         else
2325                 return strlen(sprop->defaultvalue);
2326 }
2327
2328 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
2329 {
2330         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
2331         IDProperty *idprop;
2332
2333         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2334
2335         if((idprop=rna_idproperty_check(&prop, ptr)))
2336                 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
2337         else if(sprop->set)
2338                 sprop->set(ptr, value); /* set function needs to clamp its self */
2339         else if(prop->flag & PROP_EDITABLE) {
2340                 IDProperty *group;
2341
2342                 group= RNA_struct_idprops(ptr, 1);
2343                 if(group)
2344                         IDP_AddToGroup(group, IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop) - 1));
2345         }
2346 }
2347
2348 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
2349 {
2350         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
2351
2352         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2353
2354         strcpy(value, sprop->defaultvalue);
2355 }
2356
2357 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
2358 {
2359         char *buf;
2360         int length;
2361
2362         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2363
2364         length= RNA_property_string_default_length(ptr, prop);
2365
2366         if(length+1 < fixedlen)
2367                 buf= fixedbuf;
2368         else
2369                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
2370
2371         RNA_property_string_get_default(ptr, prop, buf);
2372
2373         return buf;
2374 }
2375
2376 /* this is the length without \0 terminator */
2377 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2378 {
2379         StringPropertyRNA *sprop= (StringPropertyRNA*)prop;
2380
2381         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2382
2383         return strlen(sprop->defaultvalue);
2384 }
2385
2386 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
2387 {
2388         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
2389         IDProperty *idprop;
2390
2391         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2392
2393         if((idprop=rna_idproperty_check(&prop, ptr)))
2394                 return IDP_Int(idprop);
2395         else if(eprop->get)
2396                 return eprop->get(ptr);
2397         else
2398                 return eprop->defaultvalue;
2399 }
2400
2401 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2402 {
2403         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
2404         IDProperty *idprop;
2405
2406         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2407
2408         if((idprop=rna_idproperty_check(&prop, ptr)))
2409                 IDP_Int(idprop)= value;
2410         else if(eprop->set) {
2411                 eprop->set(ptr, value);
2412         }
2413         else if(prop->flag & PROP_EDITABLE) {
2414                 IDPropertyTemplate val = {0};
2415                 IDProperty *group;
2416
2417                 val.i= value;
2418
2419                 group= RNA_struct_idprops(ptr, 1);
2420                 if(group)
2421                         IDP_AddToGroup(group, IDP_New(IDP_INT, val, prop->identifier));
2422         }
2423 }
2424
2425 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2426 {
2427         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
2428
2429         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2430
2431         return eprop->defaultvalue;
2432 }
2433
2434 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
2435 {
2436         EnumPropertyRNA *eprop= (EnumPropertyRNA*)prop;
2437
2438         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2439
2440         return eprop->py_data;
2441 }
2442
2443 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
2444 {
2445         PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
2446         IDProperty *idprop;
2447
2448         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2449
2450         if((idprop=rna_idproperty_check(&prop, ptr))) {
2451                 pprop= (PointerPropertyRNA*)prop;
2452
2453                 /* for groups, data is idprop itself */
2454                 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
2455         }
2456         else if(pprop->get) {
2457                 return pprop->get(ptr);
2458         }
2459         else if(prop->flag & PROP_IDPROPERTY) {
2460                 /* XXX temporary hack to add it automatically, reading should
2461                    never do any write ops, to ensure thread safety etc .. */
2462                 RNA_property_pointer_add(ptr, prop);
2463                 return RNA_property_pointer_get(ptr, prop);
2464         }
2465         else {
2466                 return PointerRNA_NULL;
2467         }
2468 }
2469
2470 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
2471 {
2472         /*IDProperty *idprop;*/
2473
2474         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2475
2476         if((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
2477                 /* not supported */
2478         }
2479         else {
2480                 PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
2481
2482                 if(             pprop->set &&
2483                                 !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
2484                                 !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)
2485                 ) {
2486                         pprop->set(ptr, ptr_value);
2487                 }
2488         }
2489 }
2490
2491 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
2492 {
2493         //PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop;
2494
2495         // BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2496
2497         return PointerRNA_NULL; // FIXME: there has to be a way...
2498 }
2499
2500 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
2501 {
2502         /*IDProperty *idprop;*/
2503
2504         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2505
2506         if((/*idprop=*/rna_idproperty_check(&prop, ptr))) {
2507                 /* already exists */
2508         }
2509         else if(prop->flag & PROP_IDPROPERTY) {
2510                 IDPropertyTemplate val = {0};
2511                 IDProperty *group;
2512
2513                 val.i= 0;
2514
2515                 group= RNA_struct_idprops(ptr, 1);
2516                 if(group)
2517                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, val, prop->identifier));
2518         }
2519         else
2520                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2521 }
2522
2523 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
2524 {
2525         IDProperty *idprop, *group;
2526
2527         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2528
2529         if((idprop=rna_idproperty_check(&prop, ptr))) {
2530                 group= RNA_struct_idprops(ptr, 0);
2531                 
2532                 if(group) {
2533                         IDP_RemFromGroup(group, idprop);
2534                         IDP_FreeProperty(idprop);
2535                         MEM_freeN(idprop);
2536                 }
2537         }
2538         else
2539                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2540 }
2541
2542 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
2543 {
2544         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)iter->prop;
2545
2546         iter->ptr.data= rna_iterator_array_get(iter);
2547         iter->ptr.type= cprop->item_type;
2548         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
2549 }
2550
2551 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
2552 {
2553         IDProperty *idprop;
2554
2555         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2556
2557         memset(iter, 0, sizeof(*iter));
2558
2559         if((idprop=rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
2560                 iter->parent= *ptr;
2561                 iter->prop= prop;
2562
2563                 if(idprop)
2564                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
2565                 else
2566                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
2567
2568                 if(iter->valid)
2569                         rna_property_collection_get_idp(iter);
2570
2571                 iter->idprop= 1;
2572         }
2573         else {
2574                 CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2575                 cprop->begin(iter, ptr);
2576         }
2577 }
2578
2579 void RNA_property_collection_next(CollectionPropertyIterator *iter)
2580 {
2581         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)rna_ensure_property(iter->prop);
2582
2583         if(iter->idprop) {
2584                 rna_iterator_array_next(iter);
2585
2586                 if(iter->valid)
2587                         rna_property_collection_get_idp(iter);
2588         }
2589         else
2590                 cprop->next(iter);
2591 }
2592
2593 void RNA_property_collection_end(CollectionPropertyIterator *iter)
2594 {
2595         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)rna_ensure_property(iter->prop);
2596
2597         if(iter->idprop)
2598                 rna_iterator_array_end(iter);
2599         else
2600                 cprop->end(iter);
2601 }
2602
2603 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
2604 {
2605         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2606         IDProperty *idprop;
2607
2608         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2609
2610         if((idprop=rna_idproperty_check(&prop, ptr))) {
2611                 return idprop->len;
2612         }
2613         else if(cprop->length) {
2614                 return cprop->length(ptr);
2615         }
2616         else {
2617                 CollectionPropertyIterator iter;
2618                 int length= 0;
2619
2620                 RNA_property_collection_begin(ptr, prop, &iter);
2621                 for(; iter.valid; RNA_property_collection_next(&iter))
2622                         length++;
2623                 RNA_property_collection_end(&iter);
2624
2625                 return length;
2626         }
2627 }
2628
2629 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2630 {
2631         IDProperty *idprop;
2632 //      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2633
2634         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2635
2636         if((idprop=rna_idproperty_check(&prop, ptr))) {
2637                 IDPropertyTemplate val = {0};
2638                 IDProperty *item;
2639
2640                 item= IDP_New(IDP_GROUP, val, "");
2641                 IDP_AppendArray(idprop, item);
2642                 // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory 
2643                 MEM_freeN(item);
2644         }
2645         else if(prop->flag & PROP_IDPROPERTY) {
2646                 IDProperty *group, *item;
2647                 IDPropertyTemplate val = {0};
2648
2649                 group= RNA_struct_idprops(ptr, 1);
2650                 if(group) {
2651                         idprop= IDP_NewIDPArray(prop->identifier);
2652                         IDP_AddToGroup(group, idprop);
2653
2654                         item= IDP_New(IDP_GROUP, val, "");
2655                         IDP_AppendArray(idprop, item);
2656                         // IDP_FreeProperty(item); // IDP_AppendArray does a shallow copy (memcpy), only free memory
2657                         MEM_freeN(item);
2658                 }
2659         }
2660
2661         /* py api calls directly */
2662 #if 0
2663         else if(cprop->add){
2664                 if(!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2665                         ParameterList params;
2666                         RNA_parameter_list_create(&params, ptr, cprop->add);
2667                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
2668                         RNA_parameter_list_free(&params);
2669                 }
2670         }
2671         /*else
2672                 printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/
2673 #endif
2674
2675         if(r_ptr) {
2676                 if(idprop) {
2677                         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2678
2679                         r_ptr->data= IDP_GetIndexArray(idprop, idprop->len-1);
2680                         r_ptr->type= cprop->item_type;
2681                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
2682                 }
2683                 else
2684                         memset(r_ptr, 0, sizeof(*r_ptr));
2685         }
2686 }
2687
2688 int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
2689 {
2690         IDProperty *idprop;
2691 //      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop;
2692
2693         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2694
2695         if((idprop=rna_idproperty_check(&prop, ptr))) {
2696                 IDProperty tmp, *array;
2697                 int len;
2698
2699                 len= idprop->len;
2700                 array= IDP_IDPArray(idprop);
2701
2702                 if(key >= 0 && key < len) {
2703                         if(key+1 < len) {
2704                                 /* move element to be removed to the back */
2705                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
2706                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(len-(key+1)));
2707                                 memcpy(&array[len-1], &tmp, sizeof(IDProperty));
2708                         }
2709
2710                         IDP_ResizeIDPArray(idprop, len-1);
2711                 }
2712
2713                 return 1;
2714         }
2715         else if(prop->flag & PROP_IDPROPERTY)
2716                 return 1;
2717
2718         /* py api calls directly */
2719 #if 0
2720         else if(cprop->remove){
2721                 if(!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2722                         ParameterList params;
2723                         RNA_parameter_list_create(&params, ptr, cprop->remove);
2724                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
2725                         RNA_parameter_list_free(&params);
2726                 }
2727
2728                 return 0;
2729         }
2730         /*else
2731                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/
2732 #endif
2733         return 0;
2734 }
2735
2736 int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
2737 {
2738         IDProperty *idprop;
2739
2740         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2741
2742         if((idprop=rna_idproperty_check(&prop, ptr))) {
2743                 IDProperty tmp, *array;
2744                 int len;
2745
2746                 len= idprop->len;
2747                 array= IDP_IDPArray(idprop);
2748
2749                 if(key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
2750                         memcpy(&tmp, &array[key], sizeof(IDProperty));
2751                         if(pos < key)
2752                                 memmove(array+pos+1, array+pos, sizeof(IDProperty)*(key - pos));
2753                         else
2754                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(pos - key));
2755                         memcpy(&array[pos], &tmp, sizeof(IDProperty));
2756                 }
2757
2758                 return 1;
2759         }
2760         else if(prop->flag & PROP_IDPROPERTY)
2761                 return 1;
2762
2763         return 0;
2764 }
2765
2766 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
2767 {
2768         IDProperty *idprop;
2769
2770         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2771
2772         if((idprop=rna_idproperty_check(&prop, ptr)))
2773                 IDP_ResizeIDPArray(idprop, 0);
2774 }
2775
2776 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
2777 {
2778         CollectionPropertyIterator iter;
2779         int index= 0;
2780         
2781         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2782
2783         RNA_property_collection_begin(ptr, prop, &iter);
2784         for(index=0; iter.valid; RNA_property_collection_next(&iter), index++) {
2785                 if (iter.ptr.data == t_ptr->data)
2786                         break;
2787         }
2788         RNA_property_collection_end(&iter);
2789         
2790         /* did we find it? */
2791         if (iter.valid)
2792                 return index;
2793         else
2794                 return -1;
2795 }
2796
2797 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
2798 {
2799         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)rna_ensure_property(prop);
2800
2801         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2802
2803         if(cprop->lookupint) {
2804                 /* we have a callback defined, use it */
2805                 return cprop->lookupint(ptr, key, r_ptr);
2806         }
2807         else {
2808                 /* no callback defined, just iterate and find the nth item */
2809                 CollectionPropertyIterator iter;
2810                 int i;
2811
2812                 RNA_property_collection_begin(ptr, prop, &iter);
2813                 for(i=0; iter.valid; RNA_property_collection_next(&iter), i++) {
2814                         if(i == key) {
2815                                 *r_ptr= iter.ptr;
2816                                 break;
2817                         }
2818                 }
2819                 RNA_property_collection_end(&iter);
2820
2821                 if(!iter.valid)
2822                         memset(r_ptr, 0, sizeof(*r_ptr));
2823
2824                 return iter.valid;
2825         }
2826 }
2827
2828 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
2829 {
2830         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)rna_ensure_property(prop);
2831
2832         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2833
2834         if(cprop->lookupstring) {
2835                 /* we have a callback defined, use it */
2836                 return cprop->lookupstring(ptr, key, r_ptr);
2837         }
2838         else {
2839                 /* no callback defined, compare with name properties if they exist */
2840                 CollectionPropertyIterator iter;
2841                 PropertyRNA *nameprop;
2842                 char name[256], *nameptr;
2843                 int found= 0;
2844                 int keylen= strlen(key);
2845                 int namelen;
2846
2847                 RNA_property_collection_begin(ptr, prop, &iter);
2848                 for(; iter.valid; RNA_property_collection_next(&iter)) {
2849                         if(iter.ptr.data && iter.ptr.type->nameproperty) {
2850                                 nameprop= iter.ptr.type->nameproperty;
2851
2852                                 nameptr= RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name), &namelen);
2853
2854                                 if((keylen == namelen) && (strcmp(nameptr, key) == 0)) {
2855                                         *r_ptr= iter.ptr;
2856                                         found= 1;
2857                                 }
2858
2859                                 if((char *)&name != nameptr)
2860                                         MEM_freeN(nameptr);
2861
2862                                 if(found)
2863                                         break;
2864                         }
2865                 }
2866                 RNA_property_collection_end(&iter);
2867
2868                 if(!iter.valid)
2869                         memset(r_ptr, 0, sizeof(*r_ptr));
2870
2871                 return iter.valid;
2872         }
2873 }
2874
2875 /* zero return is an assignment error */
2876 int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
2877 {
2878         CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)rna_ensure_property(prop);
2879
2880         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2881
2882         if(cprop->assignint) {
2883                 /* we have a callback defined, use it */
2884                 return cprop->assignint(ptr, key, assign_ptr);
2885         }
2886
2887         return 0;
2888 }
2889
2890 int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2891 {
2892         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2893
2894         *r_ptr= *ptr;
2895         return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1:0);
2896 }
2897
2898 int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
2899 {
2900         CollectionPropertyIterator iter;
2901         ArrayIterator *internal;
2902         char *arrayp;
2903
2904         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2905
2906         if(!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
2907                 return 0;
2908
2909         RNA_property_collection_begin(ptr, prop, &iter);
2910
2911         if(iter.valid) {
2912                 /* get data from array iterator and item property */
2913                 internal= iter.internal;
2914                 arrayp= (iter.valid)? iter.ptr.data: NULL;
2915
2916                 if(internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
2917                         /* we might skip some items, so it's not a proper array */
2918                         RNA_property_collection_end(&iter);
2919                         return 0;
2920                 }
2921
2922                 array->array= arrayp + itemprop->rawoffset;
2923                 array->stride= internal->itemsize;
2924                 array->len= ((char*)internal->endptr - arrayp)/internal->itemsize;
2925                 array->type= itemprop->rawtype;
2926         }
2927         else
2928                 memset(array, 0, sizeof(RawArray));
2929
2930         RNA_property_collection_end(&iter);
2931
2932         return 1;
2933 }
2934
2935 #define RAW_GET(dtype, var, raw, a) \
2936 { \
2937         switch(raw.type) { \
2938                 case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break; \
2939                 case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break; \
2940                 case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break; \
2941                 case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break; \
2942                 case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break; \
2943                 default: var = (dtype)0; \
2944         } \
2945 }
2946
2947 #define RAW_SET(dtype, raw, a, var) \
2948 { \
2949         switch(raw.type) { \
2950                 case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break; \
2951                 case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break; \
2952                 case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break; \
2953                 case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break; \
2954                 case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break; \
2955                 default: break; \
2956         } \
2957 }
2958
2959 int RNA_raw_type_sizeof(RawPropertyType type)
2960 {
2961         switch(type) {
2962                 case PROP_RAW_CHAR: return sizeof(char);
2963                 case PROP_RAW_SHORT: return sizeof(short);
2964                 case PROP_RAW_INT: return sizeof(int);
2965                 case PROP_RAW_FLOAT: return sizeof(float);
2966                 case PROP_RAW_DOUBLE: return sizeof(double);
2967                 default: return 0;
2968         }
2969 }
2970
2971 static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
2972 {
2973         StructRNA *ptype;
2974         PointerRNA itemptr;
2975         PropertyRNA *itemprop, *iprop;
2976         PropertyType itemtype=0;
2977         RawArray in;
2978         int itemlen= 0;
2979
2980         /* initialize in array, stride assumed 0 in following code */
2981         in.array= inarray;
2982         in.type= intype;
2983         in.len= inlen;
2984         in.stride= 0;
2985
2986         ptype= RNA_property_pointer_type(ptr, prop);
2987
2988         /* try to get item property pointer */
2989         RNA_pointer_create(NULL, ptype, NULL, &itemptr);
2990         itemprop= RNA_struct_find_property(&itemptr, propname);
2991
2992         if(itemprop) {
2993                 /* we have item property pointer */
2994                 RawArray out;
2995
2996                 /* check type */
2997                 itemtype= RNA_property_type(itemprop);
2998
2999                 if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3000                         BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3001                         return 0;
3002                 }
3003
3004                 /* check item array */
3005                 itemlen= RNA_property_array_length(&itemptr, itemprop);
3006
3007                 /* try to access as raw array */
3008                 if(RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
3009                         int arraylen = (itemlen == 0) ? 1 : itemlen;
3010                         if(in.len != arraylen*out.len) {
3011                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d)", out.len*arraylen, in.len);
3012                                 return 0;
3013                         }
3014                         
3015                         /* matching raw types */
3016                         if(out.type == in.type) {
3017                                 void *inp= in.array;
3018                                 void *outp= out.array;
3019                                 int a, size;
3020
3021                                 size= RNA_raw_type_sizeof(out.type) * arraylen;
3022
3023                                 for(a=0; a<out.len; a++) {
3024                                         if(set) memcpy(outp, inp, size);
3025                                         else memcpy(inp, outp, size);
3026
3027                                         inp= (char*)inp + size;
3028                                         outp= (char*)outp + out.stride;
3029                                 }
3030
3031                                 return 1;
3032                         }
3033
3034                         /* could also be faster with non-matching types,
3035                          * for now we just do slower loop .. */
3036                 }
3037         }
3038
3039         {
3040                 void *tmparray= NULL;
3041                 int tmplen= 0;
3042                 int err= 0, j, a= 0;
3043                 int needconv = 1;
3044
3045                 if (((itemtype == PROP_BOOLEAN || itemtype == PROP_INT) && in.type == PROP_RAW_INT) ||
3046                         (itemtype == PROP_FLOAT && in.type == PROP_RAW_FLOAT))
3047                         /* avoid creating temporary buffer if the data type match */
3048                         needconv = 0;
3049
3050                 /* no item property pointer, can still be id property, or
3051                  * property of a type derived from the collection pointer type */
3052                 RNA_PROP_BEGIN(ptr, itemptr, prop) {
3053                         if(itemptr.data) {
3054                                 if(itemprop) {
3055                                         /* we got the property already */
3056                                         iprop= itemprop;
3057                                 }
3058                                 else {
3059                                         /* not yet, look it up and verify if it is valid */
3060                                         iprop= RNA_struct_find_property(&itemptr, propname);
3061
3062                                         if(iprop) {
3063                                                 itemlen= RNA_property_array_length(&itemptr, iprop);
3064                                                 itemtype= RNA_property_type(iprop);
3065                                         }
3066                                         else {
3067                                                 BKE_reportf(reports, RPT_ERROR, "Property named %s not found", propname);
3068                                                 err= 1;
3069                                                 break;
3070                                         }
3071
3072                                         if(!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3073                                                 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3074                                                 err= 1;
3075                                                 break;
3076                                         }
3077                                 }
3078
3079                                 /* editable check */
3080                                 if(!set || RNA_property_editable(&itemptr, iprop)) {
3081                                         if(a+itemlen > in.len) {
3082                                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more)", in.len);
3083                                                 err= 1;
3084                                                 break;
3085                                         }
3086
3087                                         if(itemlen == 0) {
3088                                                 /* handle conversions */
3089                                                 if(set) {
3090                                                         switch(itemtype) {
3091                                                                 case PROP_BOOLEAN: {
3092                                                                         int b;
3093                                                                         RAW_GET(int, b, in, a);
3094                                                                         RNA_property_boolean_set(&itemptr, iprop, b);
3095                                                                         break;
3096                                                                 }
3097                                                                 case PROP_INT: {
3098                                                                         int i;
3099                                                                         RAW_GET(int, i, in, a);
3100                                                                         RNA_property_int_set(&itemptr, iprop, i);
3101                                                                         break;
3102                                                                 }
3103                                                                 case PROP_FLOAT: {
3104                                                                         float f;
3105                                                                         RAW_GET(float, f, in, a);
3106                                                                         RNA_property_float_set(&itemptr, iprop, f);
3107                                                                         break;
3108                                                                 }
3109                                                                 default:
3110                                                                         break;
3111                                                         }
3112                                                 }
3113                                                 else {
3114                                                         switch(itemtype) {
3115                                                                 case PROP_BOOLEAN: {
3116                                                                         int b= RNA_property_boolean_get(&itemptr, iprop);
3117                                                                         RAW_SET(int, in, a, b);
3118                                                                         break;
3119                                                                 }
3120                                                                 case PROP_INT: {
3121                                                                         int i= RNA_property_int_get(&itemptr, iprop);
3122                                                                         RAW_SET(int, in, a, i);
3123                                                                         break;
3124                                                                 }
3125                                                                 case PROP_FLOAT: {
3126                                                                         float f= RNA_property_float_get(&itemptr, iprop);
3127                                                                         RAW_SET(float, in, a, f);
3128                                                                         break;
3129                                                                 }
3130                                                                 default:
3131                                                                         break;
3132                                                         }
3133                                                 }
3134                                                 a++;
3135                                         }
3136                                         else if (needconv == 1) {
3137                                                 /* allocate temporary array if needed */
3138                                                 if(tmparray && tmplen != itemlen) {
3139                                                         MEM_freeN(tmparray);
3140                                                         tmparray= NULL;
3141                                                 }
3142                                                 if(!tmparray) {
3143                                                         tmparray= MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n");
3144                                                         tmplen= itemlen;
3145                                                 }
3146
3147                                                 /* handle conversions */
3148                                                 if(set) {
3149                                                         switch(itemtype) {
3150                                                                 case PROP_BOOLEAN: {
3151                                                                         for(j=0; j<itemlen; j++, a++)
3152                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
3153                                                                         RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
3154                                                                         break;
3155                                                                 }
3156                                                                 case PROP_INT: {
3157                                                                         for(j=0; j<itemlen; j++, a++)
3158                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
3159                                                                         RNA_property_int_set_array(&itemptr, iprop, tmparray);
3160                                                                         break;
3161                                                                 }
3162                                                                 case PROP_FLOAT: {
3163                                                                         for(j=0; j<itemlen; j++, a++)
3164                                                                                 RAW_GET(float, ((float*)tmparray)[j], in, a);
3165                                                                         RNA_property_float_set_array(&itemptr, iprop, tmparray);
3166                                                                         break;
3167                                                                 }
3168                                                                 default:
3169                                                                         break;
3170                                                         }
3171                                                 }
3172                                                 else {
3173                                                         switch(itemtype) {
3174                                                                 case PROP_BOOLEAN: {
3175                                                                         RNA_property_boolean_get_array(&itemptr, iprop, tmparray);
3176                                                                         for(j=0; j<itemlen; j++, a++)
3177                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
3178                                                                         break;
3179                                                                 }
3180                                                                 case PROP_INT: {
3181                                                                         RNA_property_int_get_array(&itemptr, iprop, tmparray);
3182                                                                         for(j=0; j<itemlen; j++, a++)
3183                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
3184                                                                         break;
3185                                                                 }
3186                                                                 case PROP_FLOAT: {
3187                                                                         RNA_property_float_get_array(&itemptr, iprop, tmparray);
3188                                                                         for(j=0; j<itemlen; j++, a++)
3189                                                                                 RAW_SET(float, in, a, ((float*)tmparray)[j]);
3190                                                                         break;
3191                                                                 }
3192                                                                 default:
3193                                                                         break;
3194                                                         }
3195                                                 }
3196                                         }
3197                                         else {
3198                                                 if(set) {
3199                                                         switch(itemtype) {
3200                                                                 case PROP_BOOLEAN: {
3201                                                                         RNA_property_boolean_set_array(&itemptr, iprop, &((int*)in.array)[a]);
3202                                                                         a += itemlen;
3203                                                                         break;
3204                                                                 }
3205                                                                 case PROP_INT: {
3206                                                                         RNA_property_int_set_array(&itemptr, iprop, &((int*)in.array)[a]);
3207                                                                         a += itemlen;
3208                                                                         break;
3209                                                                 }
3210                                                                 case PROP_FLOAT: {
3211                                                                         RNA_property_float_set_array(&itemptr, iprop, &((float*)in.array)[a]);
3212                                                                         a += itemlen;
3213                                                                         break;
3214                                                                 }
3215                                                                 default:
3216                                                                         break;
3217                                                         }
3218                                                 }
3219                                                 else {
3220                                                         switch(itemtype) {
3221                                                                 case PROP_BOOLEAN: {
3222                                                                         RNA_property_boolean_get_array(&itemptr, iprop, &((int*)in.array)[a]);
3223                                                                         a += itemlen;
3224                                                                         break;
3225                                                                 }
3226                                                                 case PROP_INT: {
3227                                                                         RNA_property_int_get_array(&itemptr, iprop, &((int*)in.array)[a]);
3228                                                                         a += itemlen;
3229                                                                         break;
3230                                                                 }
3231                                                                 case PROP_FLOAT: {
3232                                                                         RNA_property_float_get_array(&itemptr, iprop, &((float*)in.array)[a]);
3233                                                                         a += itemlen;
3234                                                                         break;
3235                                                                 }
3236                                                                 default:
3237                                                                         break;
3238                                                         }
3239                                                 }
3240                                         }
3241                                 }
3242                         }
3243                 }
3244                 RNA_PROP_END;
3245
3246                 if(tmparray)
3247                         MEM_freeN(tmparray);
3248
3249                 return !err;