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