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