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