ec4da31168687464ff3bf66dda6e689d7e83a2f6
[blender.git] / source / blender / makesrna / intern / rna_access.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Foundation (2008).
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/makesrna/intern/rna_access.c
24  *  \ingroup RNA
25  */
26
27
28 #include <stdlib.h>
29 #include <stddef.h>
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_ID.h"
36 #include "DNA_scene_types.h"
37 #include "DNA_windowmanager_types.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_dynstr.h"
42 #include "BLI_ghash.h"
43
44 #include "BLF_api.h"
45 #include "BLF_translation.h"
46
47 #include "BKE_animsys.h"
48 #include "BKE_context.h"
49 #include "BKE_idprop.h"
50 #include "BKE_main.h"
51 #include "BKE_report.h"
52
53
54 #include "WM_api.h"
55
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58
59 /* flush updates */
60 #include "DNA_object_types.h"
61 #include "BKE_depsgraph.h"
62 #include "WM_types.h"
63
64 #include "rna_internal.h"
65
66 const PointerRNA PointerRNA_NULL = {{NULL}};
67
68 /* Init/Exit */
69
70 void RNA_init(void)
71 {
72         StructRNA *srna;
73         PropertyRNA *prop;
74
75         for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
76                 if (!srna->cont.prophash) {
77                         srna->cont.prophash = BLI_ghash_str_new("RNA_init gh");
78
79                         for (prop = srna->cont.properties.first; prop; prop = prop->next)
80                                 if (!(prop->flag & PROP_BUILTIN))
81                                         BLI_ghash_insert(srna->cont.prophash, (void *)prop->identifier, prop);
82                 }
83         }
84 }
85
86 void RNA_exit(void)
87 {
88         StructRNA *srna;
89         
90         RNA_property_update_cache_free();
91         
92         for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) {
93                 if (srna->cont.prophash) {
94                         BLI_ghash_free(srna->cont.prophash, NULL, NULL);
95                         srna->cont.prophash = NULL;
96                 }
97         }
98
99         RNA_free(&BLENDER_RNA);
100 }
101
102 /* Pointer */
103
104 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
105 {
106         r_ptr->id.data = NULL;
107         r_ptr->type = &RNA_BlendData;
108         r_ptr->data = main;
109 }
110
111 void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
112 {
113         StructRNA *type, *idtype = NULL;
114
115         if (id) {
116                 PointerRNA tmp = {{NULL}};
117                 tmp.data = id;
118                 idtype = rna_ID_refine(&tmp);
119                 
120                 while (idtype->refine) {
121                         type = idtype->refine(&tmp);
122
123                         if (type == idtype)
124                                 break;
125                         else
126                                 idtype = type;
127                 }
128         }
129         
130         r_ptr->id.data = id;
131         r_ptr->type = idtype;
132         r_ptr->data = id;
133 }
134
135 void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
136 {
137 #if 0 /* UNUSED */
138         StructRNA *idtype = NULL;
139
140         if (id) {
141                 PointerRNA tmp = {{0}};
142                 tmp.data = id;
143                 idtype = rna_ID_refine(&tmp);
144         }
145 #endif
146
147         r_ptr->id.data = id;
148         r_ptr->type = type;
149         r_ptr->data = data;
150
151         if (data) {
152                 while (r_ptr->type && r_ptr->type->refine) {
153                         StructRNA *rtype = r_ptr->type->refine(r_ptr);
154
155                         if (rtype == r_ptr->type)
156                                 break;
157                         else
158                                 r_ptr->type = rtype;
159                 }
160         }
161 }
162
163 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
164 {
165         if (type && type->flag & STRUCT_ID) {
166                 ptr->id.data = ptr->data;
167         }
168         else {
169                 ptr->id.data = parent->id.data;
170         }
171 }
172
173 void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
174 {
175         r_ptr->id.data = NULL;
176         r_ptr->type = &RNA_BlenderRNA;
177         r_ptr->data = &BLENDER_RNA;
178 }
179
180 PointerRNA rna_pointer_inherit_refine(PointerRNA *ptr, StructRNA *type, void *data)
181 {
182         if (data) {
183                 PointerRNA result;
184                 result.data = data;
185                 result.type = type;
186                 rna_pointer_inherit_id(type, ptr, &result);
187
188                 while (result.type->refine) {
189                         type = result.type->refine(&result);
190
191                         if (type == result.type)
192                                 break;
193                         else
194                                 result.type = type;
195                 }
196                 return result;
197         }
198         else {
199                 return PointerRNA_NULL;
200         }
201 }
202
203 /**/
204 void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
205 {
206 #if 0 /* works but this case if covered by more general code below. */
207         if (RNA_struct_is_ID(ptr->type)) {
208                 /* simple case */
209                 RNA_id_pointer_create(ptr->id.data, r_ptr);
210         }
211         else
212 #endif
213         {
214                 StructRNA *base;
215                 PointerRNA t_ptr;
216                 *r_ptr = *ptr; /* initialize as the same in case cant recast */
217
218                 for (base = ptr->type->base; base; base = base->base) {
219                         t_ptr = rna_pointer_inherit_refine(ptr, base, ptr->data);
220                         if (t_ptr.type && t_ptr.type != ptr->type) {
221                                 *r_ptr = t_ptr;
222                         }
223                 }
224         }
225 }
226
227 /* ID Properties */
228
229 static void rna_idproperty_touch(IDProperty *idprop)
230 {
231         /* so the property is seen as 'set' by rna */
232         idprop->flag &= ~IDP_FLAG_GHOST;
233 }
234
235 /* return a UI local ID prop definition for this prop */
236 IDProperty *rna_idproperty_ui(PropertyRNA *prop)
237 {
238         IDProperty *idprop;
239
240         for (idprop = ((IDProperty *)prop)->prev; idprop; idprop = idprop->prev) {
241                 if (strcmp(RNA_IDP_UI, idprop->name) == 0)
242                         break;
243         }
244
245         if (idprop == NULL) {
246                 for (idprop = ((IDProperty *)prop)->next; idprop; idprop = idprop->next) {
247                         if (strcmp(RNA_IDP_UI, idprop->name) == 0)
248                                 break;
249                 }
250         }
251
252         if (idprop) {
253                 return IDP_GetPropertyTypeFromGroup(idprop, ((IDProperty *)prop)->name, IDP_GROUP);
254         }
255
256         return NULL;
257 }
258
259 IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create)
260 {
261         StructRNA *type = ptr->type;
262
263         if (type && type->idproperties)
264                 return type->idproperties(ptr, create);
265         
266         return NULL;
267 }
268
269 int RNA_struct_idprops_check(StructRNA *srna)
270 {
271         return (srna && srna->idproperties) ? 1 : 0;
272 }
273
274 static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name)
275 {
276         IDProperty *group = RNA_struct_idprops(ptr, 0);
277
278         if (group)
279                 return IDP_GetPropertyFromGroup(group, name);
280
281         return NULL;
282 }
283
284 static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
285 {
286         if (prop->magic == RNA_MAGIC) {
287                 int arraylen[RNA_MAX_ARRAY_DIMENSION];
288                 return (prop->getlength && ptr->data) ? prop->getlength(ptr, arraylen) : prop->totarraylength;
289         }
290         else {
291                 IDProperty *idprop = (IDProperty *)prop;
292
293                 if (idprop->type == IDP_ARRAY)
294                         return idprop->len;
295                 else
296                         return 0;
297         }
298 }
299
300 static int rna_ensure_property_array_check(PropertyRNA *prop)
301 {
302         if (prop->magic == RNA_MAGIC) {
303                 return (prop->getlength || prop->totarraylength) ? 1 : 0;
304         }
305         else {
306                 IDProperty *idprop = (IDProperty *)prop;
307
308                 return idprop->type == IDP_ARRAY ? 1 : 0;
309         }
310 }
311
312 static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int length[])
313 {
314         if (prop->magic == RNA_MAGIC) {
315                 if (prop->getlength)
316                         prop->getlength(ptr, length);
317                 else
318                         memcpy(length, prop->arraylength, prop->arraydimension * sizeof(int));
319         }
320         else {
321                 IDProperty *idprop = (IDProperty *)prop;
322
323                 if (idprop->type == IDP_ARRAY)
324                         length[0] = idprop->len;
325                 else
326                         length[0] = 0;
327         }
328 }
329
330 static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop)
331 {
332         /* this verifies if the idproperty actually matches the property
333          * description and otherwise removes it. this is to ensure that
334          * rna property access is type safe, e.g. if you defined the rna
335          * to have a certain array length you can count on that staying so */
336         
337         switch (idprop->type) {
338                 case IDP_IDPARRAY:
339                         if (prop->type != PROP_COLLECTION)
340                                 return 0;
341                         break;
342                 case IDP_ARRAY:
343                         if (rna_ensure_property_array_length(ptr, prop) != idprop->len)
344                                 return 0;
345
346                         if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT)
347                                 return 0;
348                         if (idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
349                                 return 0;
350
351                         break;
352                 case IDP_INT:
353                         if (!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM))
354                                 return 0;
355                         break;
356                 case IDP_FLOAT:
357                 case IDP_DOUBLE:
358                         if (prop->type != PROP_FLOAT)
359                                 return 0;
360                         break;
361                 case IDP_STRING:
362                         if (prop->type != PROP_STRING)
363                                 return 0;
364                         break;
365                 case IDP_GROUP:
366                         if (prop->type != PROP_POINTER)
367                                 return 0;
368                         break;
369                 default:
370                         return 0;
371         }
372
373         return 1;
374 }
375
376 static PropertyRNA *typemap[IDP_NUMTYPES] = {
377         (PropertyRNA *)&rna_PropertyGroupItem_string,
378         (PropertyRNA *)&rna_PropertyGroupItem_int,
379         (PropertyRNA *)&rna_PropertyGroupItem_float,
380         NULL, NULL, NULL,
381         (PropertyRNA *)&rna_PropertyGroupItem_group, NULL,
382         (PropertyRNA *)&rna_PropertyGroupItem_double,
383         (PropertyRNA *)&rna_PropertyGroupItem_idp_array
384 };
385
386 static PropertyRNA *arraytypemap[IDP_NUMTYPES] = {
387         NULL, (PropertyRNA *)&rna_PropertyGroupItem_int_array,
388         (PropertyRNA *)&rna_PropertyGroupItem_float_array,
389         NULL, NULL, NULL,
390         (PropertyRNA *)&rna_PropertyGroupItem_collection, NULL,
391         (PropertyRNA *)&rna_PropertyGroupItem_double_array
392 };
393
394 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
395 {
396         /* This is quite a hack, but avoids some complexity in the API. we
397          * pass IDProperty structs as PropertyRNA pointers to the outside.
398          * We store some bytes in PropertyRNA structs that allows us to
399          * distinguish it from IDProperty structs. If it is an ID property,
400          * we look up an IDP PropertyRNA based on the type, and set the data
401          * pointer to the IDProperty. */
402
403         if ((*prop)->magic == RNA_MAGIC) {
404                 if ((*prop)->flag & PROP_IDPROPERTY) {
405                         IDProperty *idprop = rna_idproperty_find(ptr, (*prop)->identifier);
406
407                         if (idprop && !rna_idproperty_verify_valid(ptr, *prop, idprop)) {
408                                 IDProperty *group = RNA_struct_idprops(ptr, 0);
409
410                                 IDP_RemFromGroup(group, idprop);
411                                 IDP_FreeProperty(idprop);
412                                 MEM_freeN(idprop);
413                                 return NULL;
414                         }
415
416                         return idprop;
417                 }
418                 else
419                         return NULL;
420         }
421
422         {
423                 IDProperty *idprop = (IDProperty *)(*prop);
424
425                 if (idprop->type == IDP_ARRAY)
426                         *prop = arraytypemap[(int)(idprop->subtype)];
427                 else
428                         *prop = typemap[(int)(idprop->type)];
429
430                 return idprop;
431         }
432 }
433
434 static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
435 {
436         /* the quick version if we don't need the idproperty */
437
438         if (prop->magic == RNA_MAGIC)
439                 return prop;
440
441         {
442                 IDProperty *idprop = (IDProperty *)prop;
443
444                 if (idprop->type == IDP_ARRAY)
445                         return arraytypemap[(int)(idprop->subtype)];
446                 else
447                         return typemap[(int)(idprop->type)];
448         }
449 }
450
451 static const char *rna_ensure_property_identifier(PropertyRNA *prop)
452 {
453         if (prop->magic == RNA_MAGIC)
454                 return prop->identifier;
455         else
456                 return ((IDProperty *)prop)->name;
457 }
458
459 static const char *rna_ensure_property_description(PropertyRNA *prop)
460 {
461         const char *description = NULL;
462
463         if (prop->magic == RNA_MAGIC)
464                 description = prop->description;
465         else {
466                 /* attempt to get the local ID values */
467                 IDProperty *idp_ui = rna_idproperty_ui(prop);
468
469                 if (idp_ui) {
470                         IDProperty *item = IDP_GetPropertyTypeFromGroup(idp_ui, "description", IDP_STRING);
471                         if (item)
472                                 description = IDP_String(item);
473                 }
474
475                 if (description == NULL)
476                         description = ((IDProperty *)prop)->name;  /* XXX - not correct */
477         }
478
479         return TIP_(description);
480 }
481
482 static const char *rna_ensure_property_name(PropertyRNA *prop)
483 {
484         const char *name;
485
486         if (prop->magic == RNA_MAGIC)
487                 name = prop->name;
488         else
489                 name = ((IDProperty *)prop)->name;
490
491         return CTX_IFACE_(prop->translation_context, name);
492 }
493
494 /* Structs */
495
496 StructRNA *RNA_struct_find(const char *identifier)
497 {
498         StructRNA *type;
499         if (identifier) {
500                 for (type = BLENDER_RNA.structs.first; type; type = type->cont.next)
501                         if (strcmp(type->identifier, identifier) == 0)
502                                 return type;
503         }
504         return NULL;
505 }
506
507 const char *RNA_struct_identifier(StructRNA *type)
508 {
509         return type->identifier;
510 }
511
512 const char *RNA_struct_ui_name(StructRNA *type)
513 {
514         return CTX_IFACE_(type->translation_context, type->name);
515 }
516
517 int RNA_struct_ui_icon(StructRNA *type)
518 {
519         if (type)
520                 return type->icon;
521         else
522                 return ICON_DOT;
523 }
524
525 const char *RNA_struct_ui_description(StructRNA *type)
526 {
527         return TIP_(type->description);
528 }
529
530 const char *RNA_struct_translation_context(StructRNA *type)
531 {
532         return type->translation_context ? type->translation_context : BLF_I18NCONTEXT_DEFAULT;
533 }
534
535 PropertyRNA *RNA_struct_name_property(StructRNA *type)
536 {
537         return type->nameproperty;
538 }
539
540 PropertyRNA *RNA_struct_iterator_property(StructRNA *type)
541 {
542         return type->iteratorproperty;
543 }
544
545 StructRNA *RNA_struct_base(StructRNA *type)
546 {
547         return type->base;
548 }
549
550 int RNA_struct_is_ID(StructRNA *type)
551 {
552         return (type->flag & STRUCT_ID) != 0;
553 }
554
555 int RNA_struct_undo_check(StructRNA *type)
556 {
557         return (type->flag & STRUCT_UNDO) != 0;
558 }
559
560 int RNA_struct_idprops_register_check(StructRNA *type)
561 {
562         return (type->flag & STRUCT_NO_IDPROPERTIES) == 0;
563 }
564
565 /* remove an id-property */
566 int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier)
567 {
568         IDProperty *group = RNA_struct_idprops(ptr, 0);
569
570         if (group) {
571                 IDProperty *idp = IDP_GetPropertyFromGroup(group, identifier);
572                 if (idp) {
573                         IDP_RemFromGroup(group, idp);
574                         IDP_FreeProperty(idp);
575                         MEM_freeN(idp);
576
577                         return 1;
578                 }
579         }
580         return 0;
581 }
582
583 int RNA_struct_is_a(StructRNA *type, StructRNA *srna)
584 {
585         StructRNA *base;
586
587         if (!type)
588                 return 0;
589
590         /* ptr->type is always maximally refined */
591         for (base = type; base; base = base->base)
592                 if (base == srna)
593                         return 1;
594         
595         return 0;
596 }
597
598 PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
599 {
600         if (identifier[0] == '[' && identifier[1] == '"') { /* "  (dummy comment to avoid confusing some
601                                                                  * function lists in text editors) */
602                 /* id prop lookup, not so common */
603                 PropertyRNA *r_prop = NULL;
604                 PointerRNA r_ptr; /* only support single level props */
605                 if (RNA_path_resolve(ptr, identifier, &r_ptr, &r_prop) && r_ptr.type == ptr->type && r_ptr.data == ptr->data)
606                         return r_prop;
607         }
608         else {
609                 /* most common case */
610                 PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type);
611                 PointerRNA propptr;
612
613                 if (RNA_property_collection_lookup_string(ptr, iterprop, identifier, &propptr))
614                         return propptr.data;
615         }
616         
617         return NULL;
618 }
619
620 /* Find the property which uses the given nested struct */
621 PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
622 {
623         PropertyRNA *prop = NULL;
624
625         RNA_STRUCT_BEGIN(ptr, iprop)
626         {
627                 /* This assumes that there can only be one user of this nested struct */
628                 if (RNA_property_pointer_type(ptr, iprop) == srna) {
629                         prop = iprop;
630                         break;
631                 }
632         }
633         RNA_PROP_END;
634
635         return prop;
636 }
637
638 int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test)
639 {
640         /* note, prop_test could be freed memory, only use for comparison */
641
642         /* validate the RNA is ok */
643         PropertyRNA *iterprop;
644         int found = FALSE;
645
646         iterprop = RNA_struct_iterator_property(ptr->type);
647
648         RNA_PROP_BEGIN(ptr, itemptr, iterprop)
649         {
650                 /* PropertyRNA *prop = itemptr.data; */
651                 if (prop_test == (PropertyRNA *)itemptr.data) {
652                         found = TRUE;
653                         break;
654                 }
655         }
656         RNA_PROP_END;
657
658         return found;
659 }
660
661 /* low level direct access to type->properties, note this ignores parent classes so should be used with care */
662 const struct ListBase *RNA_struct_type_properties(StructRNA *srna)
663 {
664         return &srna->cont.properties;
665 }
666
667 PropertyRNA *RNA_struct_type_find_property(StructRNA *srna, const char *identifier)
668 {
669         return BLI_findstring_ptr(&srna->cont.properties, identifier, offsetof(PropertyRNA, identifier));
670 }
671
672 FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier)
673 {
674 #if 1
675         FunctionRNA *func;
676         StructRNA *type;
677         for (type = srna; type; type = type->base) {
678                 func = (FunctionRNA *)BLI_findstring_ptr(&type->functions, identifier, offsetof(FunctionRNA, identifier));
679                 if (func) {
680                         return func;
681                 }
682         }
683         return NULL;
684
685         /* funcitonal but slow */
686 #else
687         PointerRNA tptr;
688         PropertyRNA *iterprop;
689         FunctionRNA *func;
690
691         RNA_pointer_create(NULL, &RNA_Struct, srna, &tptr);
692         iterprop = RNA_struct_find_property(&tptr, "functions");
693
694         func = NULL;
695
696         RNA_PROP_BEGIN(&tptr, funcptr, iterprop)
697         {
698                 if (strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) {
699                         func = funcptr.data;
700                         break;
701                 }
702         }
703         RNA_PROP_END;
704
705         return func;
706 #endif
707 }
708
709 const ListBase *RNA_struct_type_functions(StructRNA *srna)
710 {
711         return &srna->functions;
712 }
713
714 StructRegisterFunc RNA_struct_register(StructRNA *type)
715 {
716         return type->reg;
717 }
718
719 StructUnregisterFunc RNA_struct_unregister(StructRNA *type)
720 {
721         do {
722                 if (type->unreg)
723                         return type->unreg;
724         } while ((type = type->base));
725
726         return NULL;
727 }
728
729 void **RNA_struct_instance(PointerRNA *ptr)
730 {
731         StructRNA *type = ptr->type;
732
733         do {
734                 if (type->instance)
735                         return type->instance(ptr);
736         } while ((type = type->base));
737
738         return NULL;
739 }
740
741 void *RNA_struct_py_type_get(StructRNA *srna)
742 {
743         return srna->py_type;
744 }
745
746 void RNA_struct_py_type_set(StructRNA *srna, void *py_type)
747 {
748         srna->py_type = py_type;
749 }
750
751 void *RNA_struct_blender_type_get(StructRNA *srna)
752 {
753         return srna->blender_type;
754 }
755
756 void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type)
757 {
758         srna->blender_type = blender_type;
759 }
760
761 char *RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
762 {
763         PropertyRNA *nameprop;
764
765         if (ptr->data && (nameprop = RNA_struct_name_property(ptr->type)))
766                 return RNA_property_string_get_alloc(ptr, nameprop, fixedbuf, fixedlen, r_len);
767
768         return NULL;
769 }
770
771 /* Property Information */
772
773 const char *RNA_property_identifier(PropertyRNA *prop)
774 {
775         return rna_ensure_property_identifier(prop);
776 }
777
778 const char *RNA_property_description(PropertyRNA *prop)
779 {
780         return rna_ensure_property_description(prop);
781 }
782
783 PropertyType RNA_property_type(PropertyRNA *prop)
784 {
785         return rna_ensure_property(prop)->type;
786 }
787
788 PropertySubType RNA_property_subtype(PropertyRNA *prop)
789 {
790         return rna_ensure_property(prop)->subtype;
791 }
792
793 PropertyUnit RNA_property_unit(PropertyRNA *prop)
794 {
795         return RNA_SUBTYPE_UNIT(rna_ensure_property(prop)->subtype);
796 }
797
798 int RNA_property_flag(PropertyRNA *prop)
799 {
800         return rna_ensure_property(prop)->flag;
801 }
802
803 void *RNA_property_py_data_get(PropertyRNA *prop)
804 {
805         return prop->py_data;
806 }
807
808 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
809 {
810         return rna_ensure_property_array_length(ptr, prop);
811 }
812
813 int RNA_property_array_check(PropertyRNA *prop)
814 {
815         return rna_ensure_property_array_check(prop);
816 }
817
818 /* used by BPY to make an array from the python object */
819 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
820 {
821         PropertyRNA *rprop = rna_ensure_property(prop);
822
823         if (length)
824                 rna_ensure_property_multi_array_length(ptr, prop, length);
825
826         return rprop->arraydimension;
827 }
828
829 /* Return the size of Nth dimension. */
830 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
831 {
832         int len[RNA_MAX_ARRAY_DIMENSION];
833
834         rna_ensure_property_multi_array_length(ptr, prop, len);
835
836         return len[dim];
837 }
838
839 char RNA_property_array_item_char(PropertyRNA *prop, int index)
840 {
841         const char *vectoritem = "XYZW";
842         const char *quatitem = "WXYZ";
843         const char *coloritem = "RGBA";
844         PropertySubType subtype = rna_ensure_property(prop)->subtype;
845
846         /* get string to use for array index */
847         if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
848                 return quatitem[index];
849         }
850         else if ((index < 4) && ELEM8(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
851                                       PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
852         {
853                 return vectoritem[index];
854         }
855         else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
856                 return coloritem[index];
857         }
858
859         return '\0';
860 }
861
862 int RNA_property_array_item_index(PropertyRNA *prop, char name)
863 {
864         PropertySubType subtype = rna_ensure_property(prop)->subtype;
865
866         /* get index based on string name/alias */
867         /* maybe a function to find char index in string would be better than all the switches */
868         if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
869                 switch (name) {
870                         case 'w':
871                                 return 0;
872                         case 'x':
873                                 return 1;
874                         case 'y':
875                                 return 2;
876                         case 'z':
877                                 return 3;
878                 }
879         }
880         else if (ELEM6(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ,
881                        PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
882         {
883                 switch (name) {
884                         case 'x':
885                                 return 0;
886                         case 'y':
887                                 return 1;
888                         case 'z':
889                                 return 2;
890                         case 'w':
891                                 return 3;
892                 }
893         }
894         else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
895                 switch (name) {
896                         case 'r':
897                                 return 0;
898                         case 'g':
899                                 return 1;
900                         case 'b':
901                                 return 2;
902                         case 'a':
903                                 return 3;
904                 }
905         }
906
907         return -1;
908 }
909
910
911 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
912 {
913         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
914         int softmin, softmax;
915
916         if (prop->magic != RNA_MAGIC) {
917                 /* attempt to get the local ID values */
918                 IDProperty *idp_ui = rna_idproperty_ui(prop);
919
920                 if (idp_ui) {
921                         IDProperty *item;
922
923                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
924                         *hardmin = item ? IDP_Int(item) : INT_MIN;
925
926                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
927                         *hardmax = item ? IDP_Int(item) : INT_MAX;
928
929                         return;
930                 }
931         }
932
933         if (iprop->range) {
934                 *hardmin = INT_MIN;
935                 *hardmax = INT_MAX;
936
937                 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
938         }
939         else {
940                 *hardmin = iprop->hardmin;
941                 *hardmax = iprop->hardmax;
942         }
943 }
944
945 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
946 {
947         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
948         int hardmin, hardmax;
949         
950         if (prop->magic != RNA_MAGIC) {
951                 /* attempt to get the local ID values */
952                 IDProperty *idp_ui = rna_idproperty_ui(prop);
953
954                 if (idp_ui) {
955                         IDProperty *item;
956
957                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
958                         *softmin = item ? IDP_Int(item) : INT_MIN;
959
960                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
961                         *softmax = item ? IDP_Int(item) : INT_MAX;
962
963                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
964                         *step = item ? IDP_Int(item) : 1;
965
966                         return;
967                 }
968         }
969
970         *softmin = iprop->softmin;
971         *softmax = iprop->softmax;
972
973         if (iprop->range) {
974                 hardmin = INT_MIN;
975                 hardmax = INT_MAX;
976
977                 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
978
979                 *softmin = MAX2(*softmin, hardmin);
980                 *softmax = MIN2(*softmax, hardmax);
981         }
982
983         *step = iprop->step;
984 }
985
986 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
987 {
988         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
989         float softmin, softmax;
990
991         if (prop->magic != RNA_MAGIC) {
992                 /* attempt to get the local ID values */
993                 IDProperty *idp_ui = rna_idproperty_ui(prop);
994
995                 if (idp_ui) {
996                         IDProperty *item;
997
998                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
999                         *hardmin = item ? (float)IDP_Double(item) : FLT_MIN;
1000
1001                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1002                         *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1003
1004                         return;
1005                 }
1006         }
1007
1008         if (fprop->range) {
1009                 *hardmin = -FLT_MAX;
1010                 *hardmax = FLT_MAX;
1011
1012                 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1013         }
1014         else {
1015                 *hardmin = fprop->hardmin;
1016                 *hardmax = fprop->hardmax;
1017         }
1018 }
1019
1020 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax,
1021                                  float *step, float *precision)
1022 {
1023         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1024         float hardmin, hardmax;
1025
1026         if (prop->magic != RNA_MAGIC) {
1027                 /* attempt to get the local ID values */
1028                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1029
1030                 if (idp_ui) {
1031                         IDProperty *item;
1032
1033                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1034                         *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1035
1036                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1037                         *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1038
1039                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1040                         *step = item ? (float)IDP_Double(item) : 1.0f;
1041
1042                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1043                         *precision = item ? (float)IDP_Double(item) : 3.0f;
1044
1045                         return;
1046                 }
1047         }
1048
1049         *softmin = fprop->softmin;
1050         *softmax = fprop->softmax;
1051
1052         if (fprop->range) {
1053                 hardmin = -FLT_MAX;
1054                 hardmax = FLT_MAX;
1055
1056                 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1057
1058                 *softmin = MAX2(*softmin, hardmin);
1059                 *softmax = MIN2(*softmax, hardmax);
1060         }
1061
1062         *step = fprop->step;
1063         *precision = (float)fprop->precision;
1064 }
1065
1066 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1067 {
1068         float min, max;
1069
1070         RNA_property_float_range(ptr, prop, &min, &max);
1071
1072         if (*value < min) {
1073                 *value = min;
1074                 return -1;
1075         }
1076         else if (*value > max) {
1077                 *value = max;
1078                 return 1;
1079         }
1080         else {
1081                 return 0;
1082         }
1083 }
1084
1085 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1086 {
1087         int min, max;
1088
1089         RNA_property_int_range(ptr, prop, &min, &max);
1090
1091         if (*value < min) {
1092                 *value = min;
1093                 return -1;
1094         }
1095         else if (*value > max) {
1096                 *value = max;
1097                 return 1;
1098         }
1099         else {
1100                 return 0;
1101         }
1102 }
1103
1104 /* this is the max length including \0 terminator.
1105  * '0' used when their is no maximum */
1106 int RNA_property_string_maxlength(PropertyRNA *prop)
1107 {
1108         StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1109         return sprop->maxlength;
1110 }
1111
1112 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1113 {
1114         prop = rna_ensure_property(prop);
1115
1116         if (prop->type == PROP_POINTER) {
1117                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1118
1119                 if (pprop->typef)
1120                         return pprop->typef(ptr);
1121                 else if (pprop->type)
1122                         return pprop->type;
1123         }
1124         else if (prop->type == PROP_COLLECTION) {
1125                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1126
1127                 if (cprop->item_type)
1128                         return cprop->item_type;
1129         }
1130         /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1131
1132         return &RNA_UnknownType;
1133 }
1134
1135 int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1136 {
1137         prop = rna_ensure_property(prop);
1138
1139         if (prop->type == PROP_POINTER) {
1140                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1141                 if (pprop->poll)
1142                         return pprop->poll(ptr, *value);
1143
1144                 return 1;
1145         }
1146
1147         printf("%s %s: is not a pointer property.\n", __func__, prop->identifier);
1148         return 0;
1149 }
1150
1151 /* Reuse for dynamic types  */
1152 EnumPropertyItem DummyRNA_NULL_items[] = {
1153         {0, NULL, 0, NULL, NULL}
1154 };
1155
1156 /* Reuse for dynamic types with default value */
1157 EnumPropertyItem DummyRNA_DEFAULT_items[] = {
1158         {0, "DEFAULT", 0, "Default", ""},
1159         {0, NULL, 0, NULL, NULL}
1160 };
1161
1162 void RNA_property_enum_items(bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item,
1163                              int *totitem, int *free)
1164 {
1165         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1166
1167         *free = 0;
1168
1169         if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1170                 int tot = 0;
1171
1172                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1173                         *item = eprop->itemf(NULL, ptr, prop, free);
1174                 else
1175                         *item = eprop->itemf(C, ptr, prop, free);
1176
1177                 if (totitem) {
1178                         if (*item) {
1179                                 for (; (*item)[tot].identifier; tot++) ;
1180                         }
1181
1182                         *totitem = tot;
1183                 }
1184
1185         }
1186         else {
1187                 *item = eprop->item;
1188                 if (totitem)
1189                         *totitem = eprop->totitem;
1190         }
1191 }
1192
1193 void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1194                                        EnumPropertyItem **item, int *totitem, int *free)
1195 {
1196         RNA_property_enum_items(C, ptr, prop, item, totitem, free);
1197
1198 #ifdef WITH_INTERNATIONAL
1199         /* Note: keep directly using BLF_gettext here, has we have already done tests like BLF_translate_iface... */
1200         if (BLF_translate_iface()) {
1201                 int i;
1202                 EnumPropertyItem *nitem;
1203
1204                 if (*free) {
1205                         nitem = *item;
1206                 }
1207                 else {
1208                         int totitem = 0;
1209
1210                         /* count */
1211                         for (i = 0; (*item)[i].identifier; i++)
1212                                 totitem++;
1213
1214                         nitem = MEM_callocN(sizeof(EnumPropertyItem) * (totitem + 1), "enum_items_gettexted");
1215
1216                         for (i = 0; (*item)[i].identifier; i++)
1217                                 nitem[i] = (*item)[i];
1218
1219                         *free = 1;
1220                 }
1221
1222                 for (i = 0; nitem[i].identifier; i++) {
1223                         if (nitem[i].name) {
1224                                 if (prop->translation_context)
1225                                         nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name);
1226                                 else
1227                                         nitem[i].name = BLF_gettext(nitem[i].name);
1228                         }
1229                         if (nitem[i].description)
1230                                 nitem[i].description = BLF_gettext(nitem[i].description);
1231                 }
1232
1233                 *item = nitem;
1234         }
1235 #endif
1236 }
1237
1238
1239 int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value)
1240 {
1241         EnumPropertyItem *item, *item_array;
1242         int free, found;
1243
1244         RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free);
1245
1246         if (item_array) {
1247                 for (item = item_array; item->identifier; item++) {
1248                         if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
1249                                 *value = item->value;
1250                                 break;
1251                         }
1252                 }
1253
1254                 found = (item->identifier != NULL); /* could be alloc'd, assign before free */
1255
1256                 if (free) {
1257                         MEM_freeN(item_array);
1258                 }
1259         }
1260         else {
1261                 found = 0;
1262         }
1263         return found;
1264 }
1265
1266 int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier)
1267 {
1268         for (; item->identifier; item++) {
1269                 if (item->identifier[0] && item->value == value) {
1270                         *identifier = item->identifier;
1271                         return 1;
1272                 }
1273         }
1274         return 0;
1275 }
1276
1277 int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier)
1278 {
1279         int index = 0;
1280         for (; item->identifier; item++) {
1281                 if (item->identifier[0] && item->value & value) {
1282                         identifier[index++] = item->identifier;
1283                 }
1284         }
1285         identifier[index] = NULL;
1286         return index;
1287 }
1288
1289 int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name)
1290 {
1291         for (; item->identifier; item++) {
1292                 if (item->identifier[0] && item->value == value) {
1293                         *name = item->name;
1294                         return 1;
1295                 }
1296         }
1297         return 0;
1298 }
1299
1300 int RNA_enum_description(EnumPropertyItem *item, const int value, const char **description)
1301 {
1302         for (; item->identifier; item++) {
1303                 if (item->identifier[0] && item->value == value) {
1304                         *description = item->description;
1305                         return 1;
1306                 }
1307         }
1308         return 0;
1309 }
1310
1311 int RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1312                                  const char **identifier)
1313 {
1314         EnumPropertyItem *item = NULL;
1315         int result, free;
1316         
1317         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1318         if (item) {
1319                 result = RNA_enum_identifier(item, value, identifier);
1320                 if (free)
1321                         MEM_freeN(item);
1322
1323                 return result;
1324         }
1325         return 0;
1326 }
1327
1328 int RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1329 {
1330         EnumPropertyItem *item = NULL;
1331         int result, free;
1332         
1333         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1334         if (item) {
1335                 result = RNA_enum_name(item, value, name);
1336                 if (free)
1337                         MEM_freeN(item);
1338                 
1339                 return result;
1340         }
1341         return 0;
1342 }
1343
1344 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1345                                           const char **identifier)
1346 {
1347         EnumPropertyItem *item = NULL;
1348         int result, free;
1349
1350         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1351         if (item) {
1352                 result = RNA_enum_bitflag_identifiers(item, value, identifier);
1353                 if (free)
1354                         MEM_freeN(item);
1355
1356                 return result;
1357         }
1358         return 0;
1359 }
1360
1361 const char *RNA_property_ui_name(PropertyRNA *prop)
1362 {
1363         return rna_ensure_property_name(prop);
1364 }
1365
1366 const char *RNA_property_ui_description(PropertyRNA *prop)
1367 {
1368         return rna_ensure_property_description(prop);
1369 }
1370
1371 const char *RNA_property_translation_context(PropertyRNA *_prop)
1372 {
1373         PropertyRNA *prop = rna_ensure_property(_prop);
1374         return prop->translation_context ? prop->translation_context : BLF_I18NCONTEXT_DEFAULT;
1375 }
1376
1377 int RNA_property_ui_icon(PropertyRNA *prop)
1378 {
1379         return rna_ensure_property(prop)->icon;
1380 }
1381
1382 int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1383 {
1384         ID *id = ptr->id.data;
1385         int flag;
1386
1387         prop = rna_ensure_property(prop);
1388         flag = prop->editable ? prop->editable(ptr) : prop->flag;
1389         return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
1390 }
1391
1392 int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
1393 {
1394         int flag;
1395
1396         prop = rna_ensure_property(prop);
1397         flag = prop->editable ? prop->editable(ptr) : prop->flag;
1398         return (flag & PROP_EDITABLE);
1399 }
1400
1401 /* same as RNA_property_editable(), except this checks individual items in an array */
1402 int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1403 {
1404         ID *id;
1405         int flag;
1406
1407         prop = rna_ensure_property(prop);
1408
1409         flag = prop->flag;
1410         
1411         if (prop->editable)
1412                 flag &= prop->editable(ptr);
1413
1414         if (prop->itemeditable)
1415                 flag &= prop->itemeditable(ptr, index);
1416
1417         id = ptr->id.data;
1418
1419         return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION));
1420 }
1421
1422 int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1423 {
1424         /* check that base ID-block can support animation data */
1425         if (!id_type_can_have_animdata(ptr->id.data))
1426                 return 0;
1427         
1428         prop = rna_ensure_property(prop);
1429
1430         if (!(prop->flag & PROP_ANIMATABLE))
1431                 return 0;
1432
1433         return (prop->flag & PROP_EDITABLE);
1434 }
1435
1436 int RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
1437 {
1438         /* would need to ask animation system */
1439
1440         return 0;
1441 }
1442
1443
1444 /* this function is to check if its possible to create a valid path from the ID
1445  * its slow so don't call in a loop */
1446 int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
1447 {
1448         char *path = RNA_path_from_ID_to_property(ptr, prop);
1449         int ret = 0;
1450
1451         if (path) {
1452                 PointerRNA id_ptr;
1453                 PointerRNA r_ptr;
1454                 PropertyRNA *r_prop;
1455
1456                 RNA_id_pointer_create(ptr->id.data, &id_ptr);
1457                 if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == TRUE) {
1458                         ret = (prop == r_prop);
1459                 }
1460                 else {
1461                         ret = FALSE;
1462                 }
1463                 MEM_freeN(path);
1464         }
1465
1466         return ret;
1467 }
1468
1469
1470 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1471 {
1472         int is_rna = (prop->magic == RNA_MAGIC);
1473         prop = rna_ensure_property(prop);
1474
1475         if (is_rna) {
1476                 if (prop->update) {
1477                         /* ideally no context would be needed for update, but there's some
1478                          * parts of the code that need it still, so we have this exception */
1479                         if (prop->flag & PROP_CONTEXT_UPDATE) {
1480                                 if (C) {
1481                                         if (prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) {
1482                                                 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
1483                                         }
1484                                         else {
1485                                                 ((ContextUpdateFunc)prop->update)(C, ptr);
1486                                         }
1487                                 }
1488                         }
1489                         else
1490                                 prop->update(bmain, scene, ptr);
1491                 }
1492                 if (prop->noteflag)
1493                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1494         }
1495         
1496         if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
1497                 /* WARNING! This is so property drivers update the display!
1498                  * not especially nice  */
1499                 DAG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
1500                 WM_main_add_notifier(NC_WINDOW, NULL);
1501         }
1502 }
1503
1504 /* must keep in sync with 'rna_property_update'
1505  * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
1506  * but this isn't likely to be a performance problem. */
1507 int RNA_property_update_check(PropertyRNA *prop)
1508 {
1509         return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
1510 }
1511
1512 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1513 {
1514         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
1515 }
1516
1517 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1518 {
1519         rna_property_update(NULL, bmain, scene, ptr, prop);
1520 }
1521
1522
1523 /* RNA Updates Cache ------------------------ */
1524 /* Overview of RNA Update cache system:
1525  *
1526  * RNA Update calls need to be cached in order to maintain reasonable performance
1527  * of the animation system (i.e. maintaining a somewhat interactive framerate)
1528  * while still allowing updates to be called (necessary in particular for modifier
1529  * property updates to actually work).
1530  *
1531  * The cache is structured with a dual-layer structure
1532  * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
1533  *        and most updates end up using just that anyways)
1534  * - L2 = Update functions to be called on those PointerRNA's
1535  */
1536
1537 /* cache element */
1538 typedef struct tRnaUpdateCacheElem {
1539         struct tRnaUpdateCacheElem *next, *prev;
1540         
1541         PointerRNA ptr;     /* L1 key - id as primary, data secondary/ignored? */
1542         ListBase L2Funcs;   /* L2 functions (LinkData<RnaUpdateFuncRef>) */
1543 } tRnaUpdateCacheElem;
1544
1545 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
1546 static ListBase rna_updates_cache = {NULL, NULL};
1547
1548 /* ........................... */
1549
1550 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
1551 {
1552         tRnaUpdateCacheElem *uce = NULL;
1553         UpdateFunc fn = NULL;
1554         LinkData *ld;
1555         short is_rna = (prop->magic == RNA_MAGIC);
1556         
1557         /* sanity check */
1558         if (ELEM(NULL, ptr, prop))
1559                 return;
1560                 
1561         prop = rna_ensure_property(prop);
1562         
1563         /* we can only handle update calls with no context args for now (makes animsys updates easier) */
1564         if ((is_rna == 0) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
1565                 return;
1566         fn = prop->update;
1567                 
1568         /* find cache element for which key matches... */
1569         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1570                 /* just match by id only for now, since most update calls that we'll encounter only really care about this */
1571                 /* TODO: later, the cache might need to have some nesting on L1 to cope better
1572                  * with these problems + some tagging to indicate we need this */
1573                 if (uce->ptr.id.data == ptr->id.data)
1574                         break;
1575         }
1576         if (uce == NULL) {
1577                 /* create new instance */
1578                 uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
1579                 BLI_addtail(&rna_updates_cache, uce);
1580                 
1581                 /* copy pointer */
1582                 RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
1583         }
1584         
1585         /* check on the update func */
1586         for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
1587                 /* stop on match - function already cached */
1588                 if (fn == ld->data)
1589                         return;
1590         }
1591         /* else... if still here, we need to add it */
1592         BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
1593 }
1594
1595 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
1596 {
1597         tRnaUpdateCacheElem *uce;
1598         
1599         /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
1600         
1601         /* execute the cached updates */
1602         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1603                 LinkData *ld;
1604                 
1605                 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
1606                         UpdateFunc fn = (UpdateFunc)ld->data;
1607                         fn(bmain, scene, &uce->ptr);
1608                 }
1609         }
1610 }
1611
1612 void RNA_property_update_cache_free(void)
1613 {
1614         tRnaUpdateCacheElem *uce, *ucn;
1615         
1616         for (uce = rna_updates_cache.first; uce; uce = ucn) {
1617                 ucn = uce->next;
1618                 
1619                 /* free L2 cache */
1620                 BLI_freelistN(&uce->L2Funcs);
1621                 
1622                 /* remove self */
1623                 BLI_freelinkN(&rna_updates_cache, uce);
1624         }
1625 }
1626
1627 /* ---------------------------------------------------------------------- */
1628
1629 /* Property Data */
1630
1631 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
1632 {
1633         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1634         IDProperty *idprop;
1635
1636         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1637         BLI_assert(RNA_property_array_check(prop) == 0);
1638
1639         if ((idprop = rna_idproperty_check(&prop, ptr)))
1640                 return IDP_Int(idprop);
1641         else if (bprop->get)
1642                 return bprop->get(ptr);
1643         else
1644                 return bprop->defaultvalue;
1645 }
1646
1647 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1648 {
1649         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
1650         IDProperty *idprop;
1651
1652         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1653         BLI_assert(RNA_property_array_check(prop) == 0);
1654
1655         /* just in case other values are passed */
1656         if (value) value = 1;
1657
1658         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1659                 IDP_Int(idprop) = value;
1660                 rna_idproperty_touch(idprop);
1661         }
1662         else if (bprop->set)
1663                 bprop->set(ptr, value);
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                 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
2554         }
2555         else if (pprop->get) {
2556                 return pprop->get(ptr);
2557         }
2558         else if (prop->flag & PROP_IDPROPERTY) {
2559                 /* XXX temporary hack to add it automatically, reading should
2560                  * never do any write ops, to ensure thread safety etc .. */
2561                 RNA_property_pointer_add(ptr, prop);
2562                 return RNA_property_pointer_get(ptr, prop);
2563         }
2564         else {
2565                 return PointerRNA_NULL;
2566         }
2567 }
2568
2569 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
2570 {
2571         /*IDProperty *idprop;*/
2572
2573         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2574
2575         if ((/*idprop = */ rna_idproperty_check(&prop, ptr))) {
2576                 /* not supported */
2577                 /* rna_idproperty_touch(idprop); */
2578         }
2579         else {
2580                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
2581
2582                 if (pprop->set &&
2583                     !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
2584                     !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
2585                 {
2586                         pprop->set(ptr, ptr_value);
2587                 }
2588         }
2589 }
2590
2591 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
2592 {
2593         /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
2594
2595         /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
2596
2597         return PointerRNA_NULL; /* FIXME: there has to be a way... */
2598 }
2599
2600 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
2601 {
2602         /*IDProperty *idprop;*/
2603
2604         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2605
2606         if ((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
2607                 /* already exists */
2608         }
2609         else if (prop->flag & PROP_IDPROPERTY) {
2610                 IDPropertyTemplate val = {0};
2611                 IDProperty *group;
2612
2613                 val.i = 0;
2614
2615                 group = RNA_struct_idprops(ptr, 1);
2616                 if (group)
2617                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
2618         }
2619         else
2620                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2621 }
2622
2623 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
2624 {
2625         IDProperty *idprop, *group;
2626
2627         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2628
2629         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2630                 group = RNA_struct_idprops(ptr, 0);
2631                 
2632                 if (group) {
2633                         IDP_RemFromGroup(group, idprop);
2634                         IDP_FreeProperty(idprop);
2635                         MEM_freeN(idprop);
2636                 }
2637         }
2638         else
2639                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2640 }
2641
2642 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
2643 {
2644         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
2645
2646         iter->ptr.data = rna_iterator_array_get(iter);
2647         iter->ptr.type = cprop->item_type;
2648         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
2649 }
2650
2651 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
2652 {
2653         IDProperty *idprop;
2654
2655         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2656
2657         memset(iter, 0, sizeof(*iter));
2658
2659         if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
2660                 iter->parent = *ptr;
2661                 iter->prop = prop;
2662
2663                 if (idprop)
2664                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
2665                 else
2666                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
2667
2668                 if (iter->valid)
2669                         rna_property_collection_get_idp(iter);
2670
2671                 iter->idprop = 1;
2672         }
2673         else {
2674                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
2675                 cprop->begin(iter, ptr);
2676         }
2677 }
2678
2679 void RNA_property_collection_next(CollectionPropertyIterator *iter)
2680 {
2681         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
2682
2683         if (iter->idprop) {
2684                 rna_iterator_array_next(iter);
2685
2686                 if (iter->valid)
2687                         rna_property_collection_get_idp(iter);
2688         }
2689         else
2690                 cprop->next(iter);
2691 }
2692
2693 void RNA_property_collection_end(CollectionPropertyIterator *iter)
2694 {
2695         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
2696
2697         if (iter->idprop)
2698                 rna_iterator_array_end(iter);
2699         else
2700                 cprop->end(iter);
2701 }
2702
2703 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
2704 {
2705         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
2706         IDProperty *idprop;
2707
2708         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2709
2710         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2711                 return idprop->len;
2712         }
2713         else if (cprop->length) {
2714                 return cprop->length(ptr);
2715         }
2716         else {
2717                 CollectionPropertyIterator iter;
2718                 int length = 0;
2719
2720                 RNA_property_collection_begin(ptr, prop, &iter);
2721                 for (; iter.valid; RNA_property_collection_next(&iter))
2722                         length++;
2723                 RNA_property_collection_end(&iter);
2724
2725                 return length;
2726         }
2727 }
2728
2729 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2730 {
2731         IDProperty *idprop;
2732 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
2733
2734         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2735
2736         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2737                 IDPropertyTemplate val = {0};
2738                 IDProperty *item;
2739
2740                 item = IDP_New(IDP_GROUP, &val, "");
2741                 IDP_AppendArray(idprop, item);
2742                 /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory  */
2743                 MEM_freeN(item);
2744         }
2745         else if (prop->flag & PROP_IDPROPERTY) {
2746                 IDProperty *group, *item;
2747                 IDPropertyTemplate val = {0};
2748
2749                 group = RNA_struct_idprops(ptr, 1);
2750                 if (group) {
2751                         idprop = IDP_NewIDPArray(prop->identifier);
2752                         IDP_AddToGroup(group, idprop);
2753
2754                         item = IDP_New(IDP_GROUP, &val, "");
2755                         IDP_AppendArray(idprop, item);
2756                         /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory */
2757                         MEM_freeN(item);
2758                 }
2759         }
2760
2761         /* py api calls directly */
2762 #if 0
2763         else if (cprop->add) {
2764                 if (!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2765                         ParameterList params;
2766                         RNA_parameter_list_create(&params, ptr, cprop->add);
2767                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
2768                         RNA_parameter_list_free(&params);
2769                 }
2770         }
2771         /*else
2772             printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/
2773 #endif
2774
2775         if (r_ptr) {
2776                 if (idprop) {
2777                         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
2778
2779                         r_ptr->data = IDP_GetIndexArray(idprop, idprop->len - 1);
2780                         r_ptr->type = cprop->item_type;
2781                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
2782                 }
2783                 else
2784                         memset(r_ptr, 0, sizeof(*r_ptr));
2785         }
2786 }
2787
2788 int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
2789 {
2790         IDProperty *idprop;
2791 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
2792
2793         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2794
2795         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2796                 IDProperty tmp, *array;
2797                 int len;
2798
2799                 len = idprop->len;
2800                 array = IDP_IDPArray(idprop);
2801
2802                 if (key >= 0 && key < len) {
2803                         if (key + 1 < len) {
2804                                 /* move element to be removed to the back */
2805                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
2806                                 memmove(array + key, array + key + 1, sizeof(IDProperty) * (len - (key + 1)));
2807                                 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
2808                         }
2809
2810                         IDP_ResizeIDPArray(idprop, len - 1);
2811                 }
2812
2813                 return 1;
2814         }
2815         else if (prop->flag & PROP_IDPROPERTY)
2816                 return 1;
2817
2818         /* py api calls directly */
2819 #if 0
2820         else if (cprop->remove) {
2821                 if (!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2822                         ParameterList params;
2823                         RNA_parameter_list_create(&params, ptr, cprop->remove);
2824                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
2825                         RNA_parameter_list_free(&params);
2826                 }
2827
2828                 return 0;
2829         }
2830         /*else
2831             printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/
2832 #endif
2833         return 0;
2834 }
2835
2836 int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
2837 {
2838         IDProperty *idprop;
2839
2840         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2841
2842         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2843                 IDProperty tmp, *array;
2844                 int len;
2845
2846                 len = idprop->len;
2847                 array = IDP_IDPArray(idprop);
2848
2849                 if (key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
2850                         memcpy(&tmp, &array[key], sizeof(IDProperty));
2851                         if (pos < key)
2852                                 memmove(array + pos + 1, array + pos, sizeof(IDProperty) * (key - pos));
2853                         else
2854                                 memmove(array + key, array + key + 1, sizeof(IDProperty) * (pos - key));
2855                         memcpy(&array[pos], &tmp, sizeof(IDProperty));
2856                 }
2857
2858                 return 1;
2859         }
2860         else if (prop->flag & PROP_IDPROPERTY)
2861                 return 1;
2862
2863         return 0;
2864 }
2865
2866 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
2867 {
2868         IDProperty *idprop;
2869
2870         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2871
2872         if ((idprop = rna_idproperty_check(&prop, ptr)))
2873                 IDP_ResizeIDPArray(idprop, 0);
2874 }
2875
2876 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
2877 {
2878         CollectionPropertyIterator iter;
2879         int index = 0;
2880         
2881         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2882
2883         RNA_property_collection_begin(ptr, prop, &iter);
2884         for (index = 0; iter.valid; RNA_property_collection_next(&iter), index++) {
2885                 if (iter.ptr.data == t_ptr->data)
2886                         break;
2887         }
2888         RNA_property_collection_end(&iter);
2889         
2890         /* did we find it? */
2891         if (iter.valid)
2892                 return index;
2893         else
2894                 return -1;
2895 }
2896
2897 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
2898 {
2899         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
2900
2901         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2902
2903         if (cprop->lookupint) {
2904                 /* we have a callback defined, use it */
2905                 return cprop->lookupint(ptr, key, r_ptr);
2906         }
2907         else {
2908                 /* no callback defined, just iterate and find the nth item */
2909                 CollectionPropertyIterator iter;
2910                 int i;
2911
2912                 RNA_property_collection_begin(ptr, prop, &iter);
2913                 for (i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
2914                         if (i == key) {
2915                                 *r_ptr = iter.ptr;
2916                                 break;
2917                         }
2918                 }
2919                 RNA_property_collection_end(&iter);
2920
2921                 if (!iter.valid)
2922                         memset(r_ptr, 0, sizeof(*r_ptr));
2923
2924                 return iter.valid;
2925         }
2926 }
2927
2928 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
2929 {
2930         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
2931
2932         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2933
2934         if (cprop->lookupstring) {
2935                 /* we have a callback defined, use it */
2936                 return cprop->lookupstring(ptr, key, r_ptr);
2937         }
2938         else {
2939                 /* no callback defined, compare with name properties if they exist */
2940                 CollectionPropertyIterator iter;
2941                 PropertyRNA *nameprop;
2942                 char name[256], *nameptr;
2943                 int found = 0;
2944                 int keylen = strlen(key);
2945                 int namelen;
2946
2947                 RNA_property_collection_begin(ptr, prop, &iter);
2948                 for (; iter.valid; RNA_property_collection_next(&iter)) {
2949                         if (iter.ptr.data && iter.ptr.type->nameproperty) {
2950                                 nameprop = iter.ptr.type->nameproperty;
2951
2952                                 nameptr = RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name), &namelen);
2953
2954                                 if ((keylen == namelen) && (strcmp(nameptr, key) == 0)) {
2955                                         *r_ptr = iter.ptr;
2956                                         found = 1;
2957                                 }
2958
2959                                 if ((char *)&name != nameptr)
2960                                         MEM_freeN(nameptr);
2961
2962                                 if (found)
2963                                         break;
2964                         }
2965                 }
2966                 RNA_property_collection_end(&iter);
2967
2968                 if (!iter.valid)
2969                         memset(r_ptr, 0, sizeof(*r_ptr));
2970
2971                 return iter.valid;
2972         }
2973 }
2974
2975 /* zero return is an assignment error */
2976 int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
2977 {
2978         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(prop);
2979
2980         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2981
2982         if (cprop->assignint) {
2983                 /* we have a callback defined, use it */
2984                 return cprop->assignint(ptr, key, assign_ptr);
2985         }
2986
2987         return 0;
2988 }
2989
2990 int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2991 {
2992         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2993
2994         *r_ptr = *ptr;
2995         return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1 : 0);
2996 }
2997
2998 int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
2999 {
3000         CollectionPropertyIterator iter;
3001         ArrayIterator *internal;
3002         char *arrayp;
3003
3004         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3005
3006         if (!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
3007                 return 0;
3008
3009         RNA_property_collection_begin(ptr, prop, &iter);
3010
3011         if (iter.valid) {
3012                 /* get data from array iterator and item property */
3013                 internal = iter.internal;
3014                 arrayp = (iter.valid) ? iter.ptr.data : NULL;
3015
3016                 if (internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
3017                         /* we might skip some items, so it's not a proper array */
3018                         RNA_property_collection_end(&iter);
3019                         return 0;
3020                 }
3021
3022                 array->array = arrayp + itemprop->rawoffset;
3023                 array->stride = internal->itemsize;
3024                 array->len = ((char *)internal->endptr - arrayp) / internal->itemsize;
3025                 array->type = itemprop->rawtype;
3026         }
3027         else
3028                 memset(array, 0, sizeof(RawArray));
3029
3030         RNA_property_collection_end(&iter);
3031
3032         return 1;
3033 }
3034
3035 #define RAW_GET(dtype, var, raw, a)                                           \
3036 {                                                                             \
3037         switch (raw.type) {                                                       \
3038                 case PROP_RAW_CHAR: var = (dtype)((char *)raw.array)[a]; break;       \
3039                 case PROP_RAW_SHORT: var = (dtype)((short *)raw.array)[a]; break;     \
3040                 case PROP_RAW_INT: var = (dtype)((int *)raw.array)[a]; break;         \
3041                 case PROP_RAW_FLOAT: var = (dtype)((float *)raw.array)[a]; break;     \
3042                 case PROP_RAW_DOUBLE: var = (dtype)((double *)raw.array)[a]; break;   \
3043                 default: var = (dtype)0;                                              \
3044         }                                                                         \
3045 } (void)0
3046
3047 #define RAW_SET(dtype, raw, a, var)                                           \
3048 {                                                                             \
3049         switch (raw.type) {                                                       \
3050                 case PROP_RAW_CHAR: ((char *)raw.array)[a] = (char)var; break;        \
3051                 case PROP_RAW_SHORT: ((short *)raw.array)[a] = (short)var; break;     \
3052                 case PROP_RAW_INT: ((int *)raw.array)[a] = (int)var; break;           \
3053                 case PROP_RAW_FLOAT: ((float *)raw.array)[a] = (float)var; break;     \
3054                 case PROP_RAW_DOUBLE: ((double *)raw.array)[a] = (double)var; break;  \
3055                 default: break;                                                       \
3056         }                                                                         \
3057 } (void)0
3058
3059 int RNA_raw_type_sizeof(RawPropertyType type)
3060 {
3061         switch (type) {
3062                 case PROP_RAW_CHAR: return sizeof(char);
3063                 case PROP_RAW_SHORT: return sizeof(short);
3064                 case PROP_RAW_INT: return sizeof(int);
3065                 case PROP_RAW_FLOAT: return sizeof(float);
3066                 case PROP_RAW_DOUBLE: return sizeof(double);
3067                 default: return 0;
3068         }
3069 }
3070
3071 static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname,
3072                           void *inarray, RawPropertyType intype, int inlen, int set)
3073 {
3074         StructRNA *ptype;
3075         PointerRNA itemptr;
3076         PropertyRNA *itemprop, *iprop;
3077         PropertyType itemtype = 0;
3078         RawArray in;
3079         int itemlen = 0;
3080
3081         /* initialize in array, stride assumed 0 in following code */
3082         in.array = inarray;
3083         in.type = intype;
3084         in.len = inlen;
3085         in.stride = 0;
3086
3087         ptype = RNA_property_pointer_type(ptr, prop);
3088
3089         /* try to get item property pointer */
3090         RNA_pointer_create(NULL, ptype, NULL, &itemptr);
3091         itemprop = RNA_struct_find_property(&itemptr, propname);
3092
3093         if (itemprop) {
3094                 /* we have item property pointer */
3095                 RawArray out;
3096
3097                 /* check type */
3098                 itemtype = RNA_property_type(itemprop);
3099
3100                 if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3101                         BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3102                         return 0;
3103                 }
3104
3105                 /* check item array */
3106                 itemlen = RNA_property_array_length(&itemptr, itemprop);
3107
3108                 /* try to access as raw array */
3109                 if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
3110                         int arraylen = (itemlen == 0) ? 1 : itemlen;
3111                         if (in.len != arraylen * out.len) {
3112                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d)",
3113                                             out.len * arraylen, in.len);
3114                                 return 0;
3115                         }
3116                         
3117                         /* matching raw types */
3118                         if (out.type == in.type) {
3119                                 void *inp = in.array;
3120                                 void *outp = out.array;
3121                                 int a, size;
3122
3123                                 size = RNA_raw_type_sizeof(out.type) * arraylen;
3124
3125                                 for (a = 0; a < out.len; a++) {
3126                                         if (set) memcpy(outp, inp, size);
3127                                         else memcpy(inp, outp, size);
3128
3129                                         inp = (char *)inp + size;
3130                                         outp = (char *)outp + out.stride;
3131                                 }
3132
3133                                 return 1;
3134                         }
3135
3136                         /* could also be faster with non-matching types,
3137                          * for now we just do slower loop .. */
3138                 }
3139         }
3140
3141         {
3142                 void *tmparray = NULL;
3143                 int tmplen = 0;
3144                 int err = 0, j, a = 0;
3145                 int needconv = 1;
3146
3147                 if (((itemtype == PROP_BOOLEAN || itemtype == PROP_INT) && in.type == PROP_RAW_INT) ||
3148                     (itemtype == PROP_FLOAT && in.type == PROP_RAW_FLOAT))
3149                 {
3150                         /* avoid creating temporary buffer if the data type match */
3151                         needconv = 0;
3152                 }
3153                 /* no item property pointer, can still be id property, or
3154                  * property of a type derived from the collection pointer type */
3155                 RNA_PROP_BEGIN(ptr, itemptr, prop)
3156                 {
3157                         if (itemptr.data) {
3158                                 if (itemprop) {
3159                                         /* we got the property already */
3160                                         iprop = itemprop;
3161                                 }
3162                                 else {
3163                                         /* not yet, look it up and verify if it is valid */
3164                                         iprop = RNA_struct_find_property(&itemptr, propname);
3165
3166                                         if (iprop) {
3167                                                 itemlen = RNA_property_array_length(&itemptr, iprop);
3168                                                 itemtype = RNA_property_type(iprop);
3169                                         }
3170                                         else {
3171                                                 BKE_reportf(reports, RPT_ERROR, "Property named %s not found", propname);
3172                                                 err = 1;
3173                                                 break;
3174                                         }
3175
3176                                         if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3177                                                 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3178                                                 err = 1;
3179                                                 break;
3180                                         }
3181                                 }
3182
3183                                 /* editable check */
3184                                 if (!set || RNA_property_editable(&itemptr, iprop)) {
3185                                         if (a + itemlen > in.len) {
3186                                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more)", in.len);
3187                                                 err = 1;
3188                                                 break;
3189                                         }
3190
3191                                         if (itemlen == 0) {
3192                                                 /* handle conversions */
3193                                                 if (set) {
3194                                                         switch (itemtype) {
3195                                                                 case PROP_BOOLEAN: {
3196                                                                         int b;
3197                                                                         RAW_GET(int, b, in, a);
3198                                                                         RNA_property_boolean_set(&itemptr, iprop, b);
3199                                                                         break;
3200                                                                 }
3201                                                                 case PROP_INT: {
3202                                                                         int i;
3203                                                                         RAW_GET(int, i, in, a);
3204                                                                         RNA_property_int_set(&itemptr, iprop, i);
3205                                                                         break;
3206                                                                 }
3207                                                                 case PROP_FLOAT: {
3208                                                                         float f;
3209                                                                         RAW_GET(float, f, in, a);
3210                                                                         RNA_property_float_set(&itemptr, iprop, f);
3211                                                                         break;
3212                                                                 }
3213                                                                 default:
3214                                                                         break;
3215                                                         }
3216                                                 }
3217                                                 else {
3218                                                         switch (itemtype) {
3219                                                                 case PROP_BOOLEAN: {
3220                                                                         int b = RNA_property_boolean_get(&itemptr, iprop);
3221                                                                         RAW_SET(int, in, a, b);
3222                                                                         break;
3223                                                                 }
3224                                                                 case PROP_INT: {
3225                                                                         int i = RNA_property_int_get(&itemptr, iprop);
3226                                                                         RAW_SET(int, in, a, i);
3227                                                                         break;
3228                                                                 }
3229                                                                 case PROP_FLOAT: {
3230                                                                         float f = RNA_property_float_get(&itemptr, iprop);
3231                                                                         RAW_SET(float, in, a, f);
3232                                                                         break;
3233                                                                 }
3234                                                                 default:
3235                                                                         break;
3236                                                         }
3237                                                 }
3238                                                 a++;
3239                                         }
3240                                         else if (needconv == 1) {
3241                                                 /* allocate temporary array if needed */
3242                                                 if (tmparray && tmplen != itemlen) {
3243                                                         MEM_freeN(tmparray);
3244                                                         tmparray = NULL;
3245                                                 }
3246                                                 if (!tmparray) {
3247                                                         tmparray = MEM_callocN(sizeof(float) * itemlen, "RNA tmparray\n");
3248                                                         tmplen = itemlen;
3249                                                 }
3250
3251                                                 /* handle conversions */
3252                                                 if (set) {
3253                                                         switch (itemtype) {
3254                                                                 case PROP_BOOLEAN: {
3255                                                                         for (j = 0; j < itemlen; j++, a++)
3256                                                                                 RAW_GET(int, ((int *)tmparray)[j], in, a);
3257                                                                         RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
3258                                                                         break;
3259                                                                 }
3260                                                                 case PROP_INT: {
3261                                                                         for (j = 0; j < itemlen; j++, a++)
3262                                                                                 RAW_GET(int, ((int *)tmparray)[j], in, a);
3263                                                                         RNA_property_int_set_array(&itemptr, iprop, tmparray);
3264                                                                         break;
3265                                                                 }
3266                                                                 case PROP_FLOAT: {
3267                                                                         for (j = 0; j < itemlen; j++, a++)
3268                                                                                 RAW_GET(float, ((float *)tmparray)[j], in, a);
3269                                                                         RNA_property_float_set_array(&itemptr, iprop, tmparray);
3270                                                                         break;
3271                                                                 }
3272                                                                 default:
3273                                                                         break;
3274                                                         }
3275                                                 }
3276                                                 else {
3277                                                         switch (itemtype) {
3278                                        &