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