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