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