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