Code cleanup in rna files (huge, higly automated with py script).
[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 incase 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                 RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop);
1434                 ret = (prop == r_prop);
1435                 MEM_freeN(path);
1436         }
1437
1438         return ret;
1439 }
1440
1441
1442 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1443 {
1444         int is_rna = (prop->magic == RNA_MAGIC);
1445         prop = rna_ensure_property(prop);
1446
1447         if (is_rna) {
1448                 if (prop->update) {
1449                         /* ideally no context would be needed for update, but there's some
1450                            parts of the code that need it still, so we have this exception */
1451                         if (prop->flag & PROP_CONTEXT_UPDATE) {
1452                                 if (C) {
1453                                         if (prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) {
1454                                                 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
1455                                         }
1456                                         else {
1457                                                 ((ContextUpdateFunc)prop->update)(C, ptr);
1458                                         }
1459                                 }
1460                         }
1461                         else
1462                                 prop->update(bmain, scene, ptr);
1463                 }
1464                 if (prop->noteflag)
1465                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1466         }
1467         
1468         if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
1469                 /* WARNING! This is so property drivers update the display!
1470                  * not especially nice  */
1471                 DAG_id_tag_update(ptr->id.data, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME);
1472                 WM_main_add_notifier(NC_WINDOW, NULL);
1473         }
1474 }
1475
1476 /* must keep in sync with 'rna_property_update'
1477  * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
1478  * but this isnt likely to be a performance problem. */
1479 int RNA_property_update_check(PropertyRNA *prop)
1480 {
1481         return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
1482 }
1483
1484 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1485 {
1486         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
1487 }
1488
1489 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1490 {
1491         rna_property_update(NULL, bmain, scene, ptr, prop);
1492 }
1493
1494
1495 /* RNA Updates Cache ------------------------ */
1496 /* Overview of RNA Update cache system:
1497  *
1498  * RNA Update calls need to be cached in order to maintain reasonable performance
1499  * of the animation system (i.e. maintaining a somewhat interactive framerate)
1500  * while still allowing updates to be called (necessary in particular for modifier
1501  * property updates to actually work).
1502  *
1503  * The cache is structured with a dual-layer structure
1504  * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
1505  *               and most updates end up using just that anyways)
1506  * - L2 = Update functions to be called on those PointerRNA's
1507  */
1508
1509 /* cache element */
1510 typedef struct tRnaUpdateCacheElem {
1511         struct tRnaUpdateCacheElem *next, *prev;
1512         
1513         PointerRNA ptr;         /* L1 key - id as primary, data secondary/ignored? */
1514         ListBase L2Funcs;       /* L2 functions (LinkData<RnaUpdateFuncRef>) */
1515 } tRnaUpdateCacheElem;
1516
1517 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
1518 static ListBase rna_updates_cache = {NULL, NULL};
1519
1520 /* ........................... */
1521
1522 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
1523 {
1524         tRnaUpdateCacheElem *uce = NULL;
1525         UpdateFunc fn = NULL;
1526         LinkData *ld;
1527         short is_rna = (prop->magic == RNA_MAGIC);
1528         
1529         /* sanity check */
1530         if (ELEM(NULL, ptr, prop))
1531                 return;
1532                 
1533         prop = rna_ensure_property(prop);
1534         
1535         /* we can only handle update calls with no context args for now (makes animsys updates easier) */
1536         if ((is_rna == 0) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
1537                 return;
1538         fn = prop->update;
1539                 
1540         /* find cache element for which key matches... */
1541         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1542                 /* just match by id only for now, since most update calls that we'll encounter only really care about this */
1543                 /* TODO: later, the cache might need to have some nesting on L1 to cope better
1544                  * with these problems + some tagging to indicate we need this */
1545                 if (uce->ptr.id.data == ptr->id.data)
1546                         break;
1547         }
1548         if (uce == NULL) {
1549                 /* create new instance */
1550                 uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
1551                 BLI_addtail(&rna_updates_cache, uce);
1552                 
1553                 /* copy pointer */
1554                 RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
1555         }
1556         
1557         /* check on the update func */
1558         for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
1559                 /* stop on match - function already cached */
1560                 if (fn == ld->data)
1561                         return;
1562         }
1563         /* else... if still here, we need to add it */
1564         BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
1565 }
1566
1567 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
1568 {
1569         tRnaUpdateCacheElem *uce;
1570         
1571         /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
1572         
1573         /* execute the cached updates */
1574         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1575                 LinkData *ld;
1576                 
1577                 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
1578                         UpdateFunc fn = (UpdateFunc)ld->data;
1579                         fn(bmain, scene, &uce->ptr);
1580                 }
1581         }
1582 }
1583
1584 void RNA_property_update_cache_free(void)
1585 {
1586         tRnaUpdateCacheElem *uce, *ucn;
1587         
1588         for (uce = rna_updates_cache.first; uce; uce = ucn) {
1589                 ucn = uce->next;
1590                 
1591                 /* free L2 cache */
1592                 BLI_freelistN(&uce->L2Funcs);
1593                 
1594                 /* remove self */
1595                 BLI_freelinkN(&rna_updates_cache, uce);
1596         }
1597 }
1598
1599 /* ---------------------------------------------------------------------- */
1600
1601 /* Property Data */
1602
1603 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
1604 {
1605         BoolPropertyRNA *bprop = (BoolPropertyRNA*)prop;
1606         IDProperty *idprop;
1607
1608         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1609         BLI_assert(RNA_property_array_check(prop) == 0);
1610
1611         if ((idprop = rna_idproperty_check(&prop, ptr)))
1612                 return IDP_Int(idprop);
1613         else if (bprop->get)
1614                 return bprop->get(ptr);
1615         else
1616                 return bprop->defaultvalue;
1617 }
1618
1619 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1620 {
1621         BoolPropertyRNA *bprop = (BoolPropertyRNA*)prop;
1622         IDProperty *idprop;
1623
1624         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1625         BLI_assert(RNA_property_array_check(prop) == 0);
1626
1627         /* just incase other values are passed */
1628         if (value) value = 1;
1629
1630         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1631                 IDP_Int(idprop) = value;
1632                 rna_idproperty_touch(idprop);
1633         }
1634         else if (bprop->set)
1635                 bprop->set(ptr, value);
1636         else if (prop->flag & PROP_EDITABLE) {
1637                 IDPropertyTemplate val = {0};
1638                 IDProperty *group;
1639
1640                 val.i = value;
1641
1642                 group = RNA_struct_idprops(ptr, 1);
1643                 if (group)
1644                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
1645         }
1646 }
1647
1648 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1649 {
1650         BoolPropertyRNA *bprop = (BoolPropertyRNA*)prop;
1651         IDProperty *idprop;
1652
1653         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1654         BLI_assert(RNA_property_array_check(prop) != 0);
1655
1656         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1657                 if (prop->arraydimension == 0)
1658                         values[0] = RNA_property_boolean_get(ptr, prop);
1659                 else
1660                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
1661         }
1662         else if (prop->arraydimension == 0)
1663                 values[0] = RNA_property_boolean_get(ptr, prop);
1664         else if (bprop->getarray)
1665                 bprop->getarray(ptr, values);
1666         else if (bprop->defaultarray)
1667                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->totarraylength);
1668         else
1669                 memset(values, 0, sizeof(int)*prop->totarraylength);
1670 }
1671
1672 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1673 {
1674         int tmp[RNA_MAX_ARRAY_LENGTH];
1675         int len = rna_ensure_property_array_length(ptr, prop);
1676
1677         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1678         BLI_assert(RNA_property_array_check(prop) != 0);
1679
1680         if (len <= RNA_MAX_ARRAY_LENGTH) {
1681                 RNA_property_boolean_get_array(ptr, prop, tmp);
1682                 return tmp[index];
1683         }
1684         else {
1685                 int *tmparray, value;
1686
1687                 tmparray = MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_index");
1688                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1689                 value = tmparray[index];
1690                 MEM_freeN(tmparray);
1691
1692                 return value;
1693         }
1694 }
1695
1696 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1697 {
1698         BoolPropertyRNA *bprop = (BoolPropertyRNA*)prop;
1699         IDProperty *idprop;
1700
1701         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1702         BLI_assert(RNA_property_array_check(prop) != 0);
1703
1704         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1705                 if (prop->arraydimension == 0)
1706                         IDP_Int(idprop) = values[0];
1707                 else
1708                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1709
1710                 rna_idproperty_touch(idprop);
1711         }
1712         else if (prop->arraydimension == 0)
1713                 RNA_property_boolean_set(ptr, prop, values[0]);
1714         else if (bprop->setarray)
1715                 bprop->setarray(ptr, values);
1716         else if (prop->flag & PROP_EDITABLE) {
1717                 IDPropertyTemplate val = {0};
1718                 IDProperty *group;
1719
1720                 val.array.len = prop->totarraylength;
1721                 val.array.type = IDP_INT;
1722
1723                 group = RNA_struct_idprops(ptr, 1);
1724                 if (group) {
1725                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
1726                         IDP_AddToGroup(group, idprop);
1727                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1728                 }
1729         }
1730 }
1731
1732 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1733 {
1734         int tmp[RNA_MAX_ARRAY_LENGTH];
1735         int len = rna_ensure_property_array_length(ptr, prop);
1736
1737         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1738         BLI_assert(RNA_property_array_check(prop) != 0);
1739
1740         if (len <= RNA_MAX_ARRAY_LENGTH) {
1741                 RNA_property_boolean_get_array(ptr, prop, tmp);
1742                 tmp[index] = value;
1743                 RNA_property_boolean_set_array(ptr, prop, tmp);
1744         }
1745         else {
1746                 int *tmparray;
1747
1748                 tmparray = MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_index");
1749                 RNA_property_boolean_get_array(ptr, prop, tmparray);
1750                 tmparray[index] = value;
1751                 RNA_property_boolean_set_array(ptr, prop, tmparray);
1752                 MEM_freeN(tmparray);
1753         }
1754 }
1755
1756 int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
1757 {
1758         BoolPropertyRNA *bprop = (BoolPropertyRNA*)prop;
1759
1760         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1761         BLI_assert(RNA_property_array_check(prop) == 0);
1762
1763         return bprop->defaultvalue;
1764 }
1765
1766 void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
1767 {
1768         BoolPropertyRNA *bprop = (BoolPropertyRNA*)prop;
1769         
1770         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1771         BLI_assert(RNA_property_array_check(prop) != 0);
1772
1773         if (prop->arraydimension == 0)
1774                 values[0] = bprop->defaultvalue;
1775         else if (bprop->defaultarray)
1776                 memcpy(values, bprop->defaultarray, sizeof(int)*prop->totarraylength);
1777         else
1778                 memset(values, 0, sizeof(int)*prop->totarraylength);
1779 }
1780
1781 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1782 {
1783         int tmp[RNA_MAX_ARRAY_LENGTH];
1784         int len = rna_ensure_property_array_length(ptr, prop);
1785
1786         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
1787         BLI_assert(RNA_property_array_check(prop) != 0);
1788
1789         if (len <= RNA_MAX_ARRAY_LENGTH) {
1790                 RNA_property_boolean_get_default_array(ptr, prop, tmp);
1791                 return tmp[index];
1792         }
1793         else {
1794                 int *tmparray, value;
1795
1796                 tmparray = MEM_callocN(sizeof(int)*len, "RNA_property_boolean_get_default_index");
1797                 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
1798                 value = tmparray[index];
1799                 MEM_freeN(tmparray);
1800
1801                 return value;
1802         }
1803 }
1804
1805 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
1806 {
1807         IntPropertyRNA *iprop = (IntPropertyRNA*)prop;
1808         IDProperty *idprop;
1809
1810         BLI_assert(RNA_property_type(prop) == PROP_INT);
1811         BLI_assert(RNA_property_array_check(prop) == 0);
1812
1813         if ((idprop = rna_idproperty_check(&prop, ptr)))
1814                 return IDP_Int(idprop);
1815         else if (iprop->get)
1816                 return iprop->get(ptr);
1817         else
1818                 return iprop->defaultvalue;
1819 }
1820
1821 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
1822 {
1823         IntPropertyRNA *iprop = (IntPropertyRNA*)prop;
1824         IDProperty *idprop;
1825
1826         BLI_assert(RNA_property_type(prop) == PROP_INT);
1827         BLI_assert(RNA_property_array_check(prop) == 0);
1828         /* useful to check on bad values but set function should clamp */
1829         /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
1830
1831         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1832                 IDP_Int(idprop) = value;
1833                 rna_idproperty_touch(idprop);
1834         }
1835         else if (iprop->set)
1836                 iprop->set(ptr, value);
1837         else if (prop->flag & PROP_EDITABLE) {
1838                 IDPropertyTemplate val = {0};
1839                 IDProperty *group;
1840
1841                 val.i = value;
1842
1843                 group = RNA_struct_idprops(ptr, 1);
1844                 if (group)
1845                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
1846         }
1847 }
1848
1849 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
1850 {
1851         IntPropertyRNA *iprop = (IntPropertyRNA*)prop;
1852         IDProperty *idprop;
1853
1854         BLI_assert(RNA_property_type(prop) == PROP_INT);
1855         BLI_assert(RNA_property_array_check(prop) != 0);
1856
1857         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1858                 if (prop->arraydimension == 0)
1859                         values[0] = RNA_property_int_get(ptr, prop);
1860                 else
1861                         memcpy(values, IDP_Array(idprop), sizeof(int)*idprop->len);
1862         }
1863         else if (prop->arraydimension == 0)
1864                 values[0] = RNA_property_int_get(ptr, prop);
1865         else if (iprop->getarray)
1866                 iprop->getarray(ptr, values);
1867         else if (iprop->defaultarray)
1868                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->totarraylength);
1869         else
1870                 memset(values, 0, sizeof(int)*prop->totarraylength);
1871 }
1872
1873 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
1874 {
1875         const int array_len = RNA_property_array_length(ptr, prop);
1876
1877         if (array_len <= 0) {
1878                 values[0] = 0;
1879                 values[1] = 0;
1880         }
1881         else if (array_len == 1) {
1882                 RNA_property_int_get_array(ptr, prop, values);
1883                 values[1] = values[0];
1884         }
1885         else {
1886                 int arr_stack[32];
1887                 int *arr;
1888                 int i;
1889
1890                 if (array_len > 32) {
1891                         arr = MEM_mallocN(sizeof(int) * array_len, "RNA_property_int_get_array_range");
1892                 }
1893                 else {
1894                         arr = arr_stack;
1895                 }
1896
1897                 RNA_property_int_get_array(ptr, prop, arr);
1898                 values[0] = values[1] = arr[0];
1899                 for (i = 1; i < array_len; i++) {
1900                         values[0] = MIN2(values[0], arr[i]);
1901                         values[1] = MAX2(values[1], arr[i]);
1902                 }
1903
1904                 if (arr != arr_stack) {
1905                         MEM_freeN(arr);
1906                 }
1907         }
1908 }
1909
1910 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1911 {
1912         int tmp[RNA_MAX_ARRAY_LENGTH];
1913         int len = rna_ensure_property_array_length(ptr, prop);
1914
1915         BLI_assert(RNA_property_type(prop) == PROP_INT);
1916         BLI_assert(RNA_property_array_check(prop) != 0);
1917
1918         if (len <= RNA_MAX_ARRAY_LENGTH) {
1919                 RNA_property_int_get_array(ptr, prop, tmp);
1920                 return tmp[index];
1921         }
1922         else {
1923                 int *tmparray, value;
1924
1925                 tmparray = MEM_callocN(sizeof(int)*len, "RNA_property_int_get_index");
1926                 RNA_property_int_get_array(ptr, prop, tmparray);
1927                 value = tmparray[index];
1928                 MEM_freeN(tmparray);
1929
1930                 return value;
1931         }
1932 }
1933
1934 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
1935 {
1936         IntPropertyRNA *iprop = (IntPropertyRNA*)prop;
1937         IDProperty *idprop;
1938
1939         BLI_assert(RNA_property_type(prop) == PROP_INT);
1940         BLI_assert(RNA_property_array_check(prop) != 0);
1941
1942         if ((idprop = rna_idproperty_check(&prop, ptr))) {
1943                 if (prop->arraydimension == 0)
1944                         IDP_Int(idprop) = values[0];
1945                 else
1946                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1947
1948                 rna_idproperty_touch(idprop);
1949         }
1950         else if (prop->arraydimension == 0)
1951                 RNA_property_int_set(ptr, prop, values[0]);
1952         else if (iprop->setarray)
1953                 iprop->setarray(ptr, values);
1954         else if (prop->flag & PROP_EDITABLE) {
1955                 IDPropertyTemplate val = {0};
1956                 IDProperty *group;
1957
1958                 val.array.len = prop->totarraylength;
1959                 val.array.type = IDP_INT;
1960
1961                 group = RNA_struct_idprops(ptr, 1);
1962                 if (group) {
1963                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
1964                         IDP_AddToGroup(group, idprop);
1965                         memcpy(IDP_Array(idprop), values, sizeof(int)*idprop->len);
1966                 }
1967         }
1968 }
1969
1970 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
1971 {
1972         int tmp[RNA_MAX_ARRAY_LENGTH];
1973         int len = rna_ensure_property_array_length(ptr, prop);
1974
1975         BLI_assert(RNA_property_type(prop) == PROP_INT);
1976         BLI_assert(RNA_property_array_check(prop) != 0);
1977
1978         if (len <= RNA_MAX_ARRAY_LENGTH) {
1979                 RNA_property_int_get_array(ptr, prop, tmp);
1980                 tmp[index] = value;
1981                 RNA_property_int_set_array(ptr, prop, tmp);
1982         }
1983         else {
1984                 int *tmparray;
1985
1986                 tmparray = MEM_callocN(sizeof(int)*len, "RNA_property_int_get_index");
1987                 RNA_property_int_get_array(ptr, prop, tmparray);
1988                 tmparray[index] = value;
1989                 RNA_property_int_set_array(ptr, prop, tmparray);
1990                 MEM_freeN(tmparray);
1991         }
1992 }
1993
1994 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
1995 {
1996         IntPropertyRNA *iprop = (IntPropertyRNA*)prop;
1997         return iprop->defaultvalue;
1998 }
1999
2000 void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2001 {
2002         IntPropertyRNA *iprop = (IntPropertyRNA*)prop;
2003         
2004         BLI_assert(RNA_property_type(prop) == PROP_INT);
2005         BLI_assert(RNA_property_array_check(prop) != 0);
2006
2007         if (prop->arraydimension == 0)
2008                 values[0] = iprop->defaultvalue;
2009         else if (iprop->defaultarray)
2010                 memcpy(values, iprop->defaultarray, sizeof(int)*prop->totarraylength);
2011         else
2012                 memset(values, 0, sizeof(int)*prop->totarraylength);
2013 }
2014
2015 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2016 {
2017         int tmp[RNA_MAX_ARRAY_LENGTH];
2018         int len = rna_ensure_property_array_length(ptr, prop);
2019
2020         if (len <= RNA_MAX_ARRAY_LENGTH) {
2021                 RNA_property_int_get_default_array(ptr, prop, tmp);
2022                 return tmp[index];
2023         }
2024         else {
2025                 int *tmparray, value;
2026
2027                 tmparray = MEM_callocN(sizeof(int)*len, "RNA_property_int_get_default_index");
2028                 RNA_property_int_get_default_array(ptr, prop, tmparray);
2029                 value = tmparray[index];
2030                 MEM_freeN(tmparray);
2031
2032                 return value;
2033         }
2034 }
2035
2036 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
2037 {
2038         FloatPropertyRNA *fprop = (FloatPropertyRNA*)prop;
2039         IDProperty *idprop;
2040
2041         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2042         BLI_assert(RNA_property_array_check(prop) == 0);
2043
2044         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2045                 if (idprop->type == IDP_FLOAT)
2046                         return IDP_Float(idprop);
2047                 else
2048                         return (float)IDP_Double(idprop);
2049         }
2050         else if (fprop->get)
2051                 return fprop->get(ptr);
2052         else
2053                 return fprop->defaultvalue;
2054 }
2055
2056 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
2057 {
2058         FloatPropertyRNA *fprop = (FloatPropertyRNA*)prop;
2059         IDProperty *idprop;
2060
2061         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2062         BLI_assert(RNA_property_array_check(prop) == 0);
2063         /* useful to check on bad values but set function should clamp */
2064         /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
2065
2066         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2067                 if (idprop->type == IDP_FLOAT)
2068                         IDP_Float(idprop) = value;
2069                 else
2070                         IDP_Double(idprop) = value;
2071
2072                 rna_idproperty_touch(idprop);
2073         }
2074         else if (fprop->set) {
2075                 fprop->set(ptr, value);
2076         }
2077         else if (prop->flag & PROP_EDITABLE) {
2078                 IDPropertyTemplate val = {0};
2079                 IDProperty *group;
2080
2081                 val.f = value;
2082
2083                 group = RNA_struct_idprops(ptr, 1);
2084                 if (group)
2085                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
2086         }
2087 }
2088
2089 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
2090 {
2091         FloatPropertyRNA *fprop = (FloatPropertyRNA*)prop;
2092         IDProperty *idprop;
2093         int i;
2094
2095         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2096         BLI_assert(RNA_property_array_check(prop) != 0);
2097
2098         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2099                 if (prop->arraydimension == 0)
2100                         values[0] = RNA_property_float_get(ptr, prop);
2101                 else if (idprop->subtype == IDP_FLOAT) {
2102                         memcpy(values, IDP_Array(idprop), sizeof(float)*idprop->len);
2103                 }
2104                 else {
2105                         for (i = 0; i<idprop->len; i++)
2106                                 values[i] =  (float)(((double*)IDP_Array(idprop))[i]);
2107                 }
2108         }
2109         else if (prop->arraydimension == 0)
2110                 values[0] = RNA_property_float_get(ptr, prop);
2111         else if (fprop->getarray)
2112                 fprop->getarray(ptr, values);
2113         else if (fprop->defaultarray)
2114                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->totarraylength);
2115         else
2116                 memset(values, 0, sizeof(float)*prop->totarraylength);
2117 }
2118
2119 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
2120 {
2121         const int array_len = RNA_property_array_length(ptr, prop);
2122
2123         if (array_len <= 0) {
2124                 values[0] = 0.0f;
2125                 values[1] = 0.0f;
2126         }
2127         else if (array_len == 1) {
2128                 RNA_property_float_get_array(ptr, prop, values);
2129                 values[1] = values[0];
2130         }
2131         else {
2132                 float arr_stack[32];
2133                 float *arr;
2134                 int i;
2135
2136                 if (array_len > 32) {
2137                         arr = MEM_mallocN(sizeof(float) * array_len, "RNA_property_float_get_array_range");
2138                 }
2139                 else {
2140                         arr = arr_stack;
2141                 }
2142
2143                 RNA_property_float_get_array(ptr, prop, arr);
2144                 values[0] = values[1] = arr[0];
2145                 for (i = 1; i < array_len; i++) {
2146                         values[0] = MIN2(values[0], arr[i]);
2147                         values[1] = MAX2(values[1], arr[i]);
2148                 }
2149
2150                 if (arr != arr_stack) {
2151                         MEM_freeN(arr);
2152                 }
2153         }
2154 }
2155
2156 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2157 {
2158         float tmp[RNA_MAX_ARRAY_LENGTH];
2159         int len = rna_ensure_property_array_length(ptr, prop);
2160
2161         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2162         BLI_assert(RNA_property_array_check(prop) != 0);
2163
2164         if (len <= RNA_MAX_ARRAY_LENGTH) {
2165                 RNA_property_float_get_array(ptr, prop, tmp);
2166                 return tmp[index];
2167         }
2168         else {
2169                 float *tmparray, value;
2170
2171                 tmparray = MEM_callocN(sizeof(float)*len, "RNA_property_float_get_index");
2172                 RNA_property_float_get_array(ptr, prop, tmparray);
2173                 value = tmparray[index];
2174                 MEM_freeN(tmparray);
2175
2176                 return value;
2177         }
2178
2179 }
2180
2181 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
2182 {
2183         FloatPropertyRNA *fprop = (FloatPropertyRNA*)prop;
2184         IDProperty *idprop;
2185         int i;
2186
2187         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2188         BLI_assert(RNA_property_array_check(prop) != 0);
2189
2190         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2191                 if (prop->arraydimension == 0) {
2192                         if (idprop->type == IDP_FLOAT)
2193                                 IDP_Float(idprop) = values[0];
2194                         else
2195                                 IDP_Double(idprop) = values[0];
2196                 }
2197                 else if (idprop->subtype == IDP_FLOAT) {
2198                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
2199                 }
2200                 else {
2201                         for (i = 0; i<idprop->len; i++)
2202                                 ((double*)IDP_Array(idprop))[i] = values[i];
2203                 }
2204
2205                 rna_idproperty_touch(idprop);
2206         }
2207         else if (prop->arraydimension == 0)
2208                 RNA_property_float_set(ptr, prop, values[0]);
2209         else if (fprop->setarray) {
2210                 fprop->setarray(ptr, values);
2211         }
2212         else if (prop->flag & PROP_EDITABLE) {
2213                 IDPropertyTemplate val = {0};
2214                 IDProperty *group;
2215
2216                 val.array.len = prop->totarraylength;
2217                 val.array.type = IDP_FLOAT;
2218
2219                 group = RNA_struct_idprops(ptr, 1);
2220                 if (group) {
2221                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2222                         IDP_AddToGroup(group, idprop);
2223                         memcpy(IDP_Array(idprop), values, sizeof(float)*idprop->len);
2224                 }
2225         }
2226 }
2227
2228 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
2229 {
2230         float tmp[RNA_MAX_ARRAY_LENGTH];
2231         int len = rna_ensure_property_array_length(ptr, prop);
2232
2233         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2234         BLI_assert(RNA_property_array_check(prop) != 0);
2235
2236         if (len <= RNA_MAX_ARRAY_LENGTH) {
2237                 RNA_property_float_get_array(ptr, prop, tmp);
2238                 tmp[index] = value;
2239                 RNA_property_float_set_array(ptr, prop, tmp);
2240         }
2241         else {
2242                 float *tmparray;
2243
2244                 tmparray = MEM_callocN(sizeof(float)*len, "RNA_property_float_get_index");
2245                 RNA_property_float_get_array(ptr, prop, tmparray);
2246                 tmparray[index] = value;
2247                 RNA_property_float_set_array(ptr, prop, tmparray);
2248                 MEM_freeN(tmparray);
2249         }
2250 }
2251
2252 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2253 {
2254         FloatPropertyRNA *fprop = (FloatPropertyRNA*)prop;
2255
2256         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2257         BLI_assert(RNA_property_array_check(prop) == 0);
2258
2259         return fprop->defaultvalue;
2260 }
2261
2262 void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, float *values)
2263 {
2264         FloatPropertyRNA *fprop = (FloatPropertyRNA*)prop;
2265         
2266         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2267         BLI_assert(RNA_property_array_check(prop) != 0);
2268
2269         if (prop->arraydimension == 0)
2270                 values[0] = fprop->defaultvalue;
2271         else if (fprop->defaultarray)
2272                 memcpy(values, fprop->defaultarray, sizeof(float)*prop->totarraylength);
2273         else
2274                 memset(values, 0, sizeof(float)*prop->totarraylength);
2275 }
2276
2277 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2278 {
2279         float tmp[RNA_MAX_ARRAY_LENGTH];
2280         int len = rna_ensure_property_array_length(ptr, prop);
2281
2282         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2283         BLI_assert(RNA_property_array_check(prop) != 0);
2284
2285         if (len <= RNA_MAX_ARRAY_LENGTH) {
2286                 RNA_property_float_get_default_array(ptr, prop, tmp);
2287                 return tmp[index];
2288         }
2289         else {
2290                 float *tmparray, value;
2291
2292                 tmparray = MEM_callocN(sizeof(float)*len, "RNA_property_float_get_default_index");
2293                 RNA_property_float_get_default_array(ptr, prop, tmparray);
2294                 value = tmparray[index];
2295                 MEM_freeN(tmparray);
2296
2297                 return value;
2298         }
2299 }
2300
2301 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
2302 {
2303         StringPropertyRNA *sprop = (StringPropertyRNA*)prop;
2304         IDProperty *idprop;
2305
2306         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2307
2308         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2309                 /* editing bytes is not 100% supported
2310                  * since they can contain NIL chars */
2311                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2312                         memcpy(value, IDP_String(idprop), idprop->len);
2313                         value[idprop->len] = '\0';
2314                 }
2315                 else {
2316                         memcpy(value, IDP_String(idprop), idprop->len);
2317                 }
2318         }
2319         else if (sprop->get) {
2320                 sprop->get(ptr, value);
2321         }
2322         else {
2323                 strcpy(value, sprop->defaultvalue);
2324         }
2325 }
2326
2327 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop,
2328                                     char *fixedbuf, int fixedlen, int *r_len)
2329 {
2330         char *buf;
2331         int length;
2332
2333         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2334
2335         length = RNA_property_string_length(ptr, prop);
2336
2337         if (length+1 < fixedlen)
2338                 buf = fixedbuf;
2339         else
2340                 buf = MEM_mallocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
2341
2342 #ifndef NDEBUG
2343         /* safety check to ensure the string is actually set */
2344         buf[length] = 255;
2345 #endif
2346
2347         RNA_property_string_get(ptr, prop, buf);
2348
2349 #ifndef NDEBUG
2350         BLI_assert(buf[length] == '\0');
2351 #endif
2352
2353         if (r_len) {
2354                 *r_len = length;
2355         }
2356
2357         return buf;
2358 }
2359
2360 /* this is the length without \0 terminator */
2361 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
2362 {
2363         StringPropertyRNA *sprop = (StringPropertyRNA*)prop;
2364         IDProperty *idprop;
2365
2366         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2367
2368         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2369                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2370                         return idprop->len;
2371                 }
2372                 else {
2373 #ifndef NDEBUG
2374                         /* these _must_ stay in sync */
2375                         BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
2376 #endif
2377                         return idprop->len - 1;
2378                 }
2379         }
2380         else if (sprop->length)
2381                 return sprop->length(ptr);
2382         else
2383                 return strlen(sprop->defaultvalue);
2384 }
2385
2386 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
2387 {
2388         StringPropertyRNA *sprop = (StringPropertyRNA*)prop;
2389         IDProperty *idprop;
2390
2391         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2392
2393         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2394                 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
2395                 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
2396                 rna_idproperty_touch(idprop);
2397         }
2398         else if (sprop->set)
2399                 sprop->set(ptr, value); /* set function needs to clamp its self */
2400         else if (prop->flag & PROP_EDITABLE) {
2401                 IDProperty *group;
2402
2403                 group = RNA_struct_idprops(ptr, 1);
2404                 if (group)
2405                         IDP_AddToGroup(group, IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop) - 1));
2406         }
2407 }
2408
2409 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
2410 {
2411         StringPropertyRNA *sprop = (StringPropertyRNA*)prop;
2412
2413         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2414
2415         strcpy(value, sprop->defaultvalue);
2416 }
2417
2418 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
2419 {
2420         char *buf;
2421         int length;
2422
2423         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2424
2425         length = RNA_property_string_default_length(ptr, prop);
2426
2427         if (length+1 < fixedlen)
2428                 buf = fixedbuf;
2429         else
2430                 buf = MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
2431
2432         RNA_property_string_get_default(ptr, prop, buf);
2433
2434         return buf;
2435 }
2436
2437 /* this is the length without \0 terminator */
2438 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2439 {
2440         StringPropertyRNA *sprop = (StringPropertyRNA*)prop;
2441
2442         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2443
2444         return strlen(sprop->defaultvalue);
2445 }
2446
2447 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
2448 {
2449         EnumPropertyRNA *eprop = (EnumPropertyRNA*)prop;
2450         IDProperty *idprop;
2451
2452         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2453
2454         if ((idprop = rna_idproperty_check(&prop, ptr)))
2455                 return IDP_Int(idprop);
2456         else if (eprop->get)
2457                 return eprop->get(ptr);
2458         else
2459                 return eprop->defaultvalue;
2460 }
2461
2462 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2463 {
2464         EnumPropertyRNA *eprop = (EnumPropertyRNA*)prop;
2465         IDProperty *idprop;
2466
2467         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2468
2469         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2470                 IDP_Int(idprop) = value;
2471                 rna_idproperty_touch(idprop);
2472         }
2473         else if (eprop->set) {
2474                 eprop->set(ptr, value);
2475         }
2476         else if (prop->flag & PROP_EDITABLE) {
2477                 IDPropertyTemplate val = {0};
2478                 IDProperty *group;
2479
2480                 val.i = value;
2481
2482                 group = RNA_struct_idprops(ptr, 1);
2483                 if (group)
2484                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2485         }
2486 }
2487
2488 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2489 {
2490         EnumPropertyRNA *eprop = (EnumPropertyRNA*)prop;
2491
2492         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2493
2494         return eprop->defaultvalue;
2495 }
2496
2497 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
2498 {
2499         EnumPropertyRNA *eprop = (EnumPropertyRNA*)prop;
2500
2501         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2502
2503         return eprop->py_data;
2504 }
2505
2506 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
2507 {
2508         PointerPropertyRNA *pprop = (PointerPropertyRNA*)prop;
2509         IDProperty *idprop;
2510
2511         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2512
2513         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2514                 pprop = (PointerPropertyRNA*)prop;
2515
2516                 /* for groups, data is idprop itself */
2517                 return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
2518         }
2519         else if (pprop->get) {
2520                 return pprop->get(ptr);
2521         }
2522         else if (prop->flag & PROP_IDPROPERTY) {
2523                 /* XXX temporary hack to add it automatically, reading should
2524                    never do any write ops, to ensure thread safety etc .. */
2525                 RNA_property_pointer_add(ptr, prop);
2526                 return RNA_property_pointer_get(ptr, prop);
2527         }
2528         else {
2529                 return PointerRNA_NULL;
2530         }
2531 }
2532
2533 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
2534 {
2535         /*IDProperty *idprop;*/
2536
2537         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2538
2539         if ((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
2540                 /* not supported */
2541                 /* rna_idproperty_touch(idprop); */
2542         }
2543         else {
2544                 PointerPropertyRNA *pprop = (PointerPropertyRNA*)prop;
2545
2546                 if (            pprop->set &&
2547                                 !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
2548                                 !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)
2549                 ) {
2550                         pprop->set(ptr, ptr_value);
2551                 }
2552         }
2553 }
2554
2555 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
2556 {
2557         /*PointerPropertyRNA *pprop= (PointerPropertyRNA*)prop; */
2558
2559         /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
2560
2561         return PointerRNA_NULL; /* FIXME: there has to be a way... */
2562 }
2563
2564 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
2565 {
2566         /*IDProperty *idprop;*/
2567
2568         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2569
2570         if ((/*idprop=*/rna_idproperty_check(&prop, ptr))) {
2571                 /* already exists */
2572         }
2573         else if (prop->flag & PROP_IDPROPERTY) {
2574                 IDPropertyTemplate val = {0};
2575                 IDProperty *group;
2576
2577                 val.i = 0;
2578
2579                 group = RNA_struct_idprops(ptr, 1);
2580                 if (group)
2581                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
2582         }
2583         else
2584                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2585 }
2586
2587 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
2588 {
2589         IDProperty *idprop, *group;
2590
2591         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
2592
2593         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2594                 group = RNA_struct_idprops(ptr, 0);
2595                 
2596                 if (group) {
2597                         IDP_RemFromGroup(group, idprop);
2598                         IDP_FreeProperty(idprop);
2599                         MEM_freeN(idprop);
2600                 }
2601         }
2602         else
2603                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
2604 }
2605
2606 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
2607 {
2608         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)iter->prop;
2609
2610         iter->ptr.data = rna_iterator_array_get(iter);
2611         iter->ptr.type = cprop->item_type;
2612         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
2613 }
2614
2615 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
2616 {
2617         IDProperty *idprop;
2618
2619         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2620
2621         memset(iter, 0, sizeof(*iter));
2622
2623         if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
2624                 iter->parent = *ptr;
2625                 iter->prop = prop;
2626
2627                 if (idprop)
2628                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
2629                 else
2630                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
2631
2632                 if (iter->valid)
2633                         rna_property_collection_get_idp(iter);
2634
2635                 iter->idprop = 1;
2636         }
2637         else {
2638                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)prop;
2639                 cprop->begin(iter, ptr);
2640         }
2641 }
2642
2643 void RNA_property_collection_next(CollectionPropertyIterator *iter)
2644 {
2645         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)rna_ensure_property(iter->prop);
2646
2647         if (iter->idprop) {
2648                 rna_iterator_array_next(iter);
2649
2650                 if (iter->valid)
2651                         rna_property_collection_get_idp(iter);
2652         }
2653         else
2654                 cprop->next(iter);
2655 }
2656
2657 void RNA_property_collection_end(CollectionPropertyIterator *iter)
2658 {
2659         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)rna_ensure_property(iter->prop);
2660
2661         if (iter->idprop)
2662                 rna_iterator_array_end(iter);
2663         else
2664                 cprop->end(iter);
2665 }
2666
2667 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
2668 {
2669         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)prop;
2670         IDProperty *idprop;
2671
2672         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2673
2674         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2675                 return idprop->len;
2676         }
2677         else if (cprop->length) {
2678                 return cprop->length(ptr);
2679         }
2680         else {
2681                 CollectionPropertyIterator iter;
2682                 int length = 0;
2683
2684                 RNA_property_collection_begin(ptr, prop, &iter);
2685                 for (; iter.valid; RNA_property_collection_next(&iter))
2686                         length++;
2687                 RNA_property_collection_end(&iter);
2688
2689                 return length;
2690         }
2691 }
2692
2693 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2694 {
2695         IDProperty *idprop;
2696 /*      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; */
2697
2698         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2699
2700         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2701                 IDPropertyTemplate val = {0};
2702                 IDProperty *item;
2703
2704                 item = IDP_New(IDP_GROUP, &val, "");
2705                 IDP_AppendArray(idprop, item);
2706                 /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory  */
2707                 MEM_freeN(item);
2708         }
2709         else if (prop->flag & PROP_IDPROPERTY) {
2710                 IDProperty *group, *item;
2711                 IDPropertyTemplate val = {0};
2712
2713                 group = RNA_struct_idprops(ptr, 1);
2714                 if (group) {
2715                         idprop = IDP_NewIDPArray(prop->identifier);
2716                         IDP_AddToGroup(group, idprop);
2717
2718                         item = IDP_New(IDP_GROUP, &val, "");
2719                         IDP_AppendArray(idprop, item);
2720                         /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory */
2721                         MEM_freeN(item);
2722                 }
2723         }
2724
2725         /* py api calls directly */
2726 #if 0
2727         else if (cprop->add){
2728                 if (!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2729                         ParameterList params;
2730                         RNA_parameter_list_create(&params, ptr, cprop->add);
2731                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
2732                         RNA_parameter_list_free(&params);
2733                 }
2734         }
2735         /*else
2736                 printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/
2737 #endif
2738
2739         if (r_ptr) {
2740                 if (idprop) {
2741                         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)prop;
2742
2743                         r_ptr->data = IDP_GetIndexArray(idprop, idprop->len-1);
2744                         r_ptr->type = cprop->item_type;
2745                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
2746                 }
2747                 else
2748                         memset(r_ptr, 0, sizeof(*r_ptr));
2749         }
2750 }
2751
2752 int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
2753 {
2754         IDProperty *idprop;
2755 /*      CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; */
2756
2757         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2758
2759         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2760                 IDProperty tmp, *array;
2761                 int len;
2762
2763                 len = idprop->len;
2764                 array = IDP_IDPArray(idprop);
2765
2766                 if (key >= 0 && key < len) {
2767                         if (key+1 < len) {
2768                                 /* move element to be removed to the back */
2769                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
2770                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(len-(key+1)));
2771                                 memcpy(&array[len-1], &tmp, sizeof(IDProperty));
2772                         }
2773
2774                         IDP_ResizeIDPArray(idprop, len-1);
2775                 }
2776
2777                 return 1;
2778         }
2779         else if (prop->flag & PROP_IDPROPERTY)
2780                 return 1;
2781
2782         /* py api calls directly */
2783 #if 0
2784         else if (cprop->remove){
2785                 if (!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
2786                         ParameterList params;
2787                         RNA_parameter_list_create(&params, ptr, cprop->remove);
2788                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
2789                         RNA_parameter_list_free(&params);
2790                 }
2791
2792                 return 0;
2793         }
2794         /*else
2795                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/
2796 #endif
2797         return 0;
2798 }
2799
2800 int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos)
2801 {
2802         IDProperty *idprop;
2803
2804         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2805
2806         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2807                 IDProperty tmp, *array;
2808                 int len;
2809
2810                 len = idprop->len;
2811                 array = IDP_IDPArray(idprop);
2812
2813                 if (key >= 0 && key < len && pos >= 0 && pos < len && key != pos) {
2814                         memcpy(&tmp, &array[key], sizeof(IDProperty));
2815                         if (pos < key)
2816                                 memmove(array+pos+1, array+pos, sizeof(IDProperty)*(key - pos));
2817                         else
2818                                 memmove(array+key, array+key+1, sizeof(IDProperty)*(pos - key));
2819                         memcpy(&array[pos], &tmp, sizeof(IDProperty));
2820                 }
2821
2822                 return 1;
2823         }
2824         else if (prop->flag & PROP_IDPROPERTY)
2825                 return 1;
2826
2827         return 0;
2828 }
2829
2830 void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop)
2831 {
2832         IDProperty *idprop;
2833
2834         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2835
2836         if ((idprop = rna_idproperty_check(&prop, ptr)))
2837                 IDP_ResizeIDPArray(idprop, 0);
2838 }
2839
2840 int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr)
2841 {
2842         CollectionPropertyIterator iter;
2843         int index = 0;
2844         
2845         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2846
2847         RNA_property_collection_begin(ptr, prop, &iter);
2848         for (index = 0; iter.valid; RNA_property_collection_next(&iter), index++) {
2849                 if (iter.ptr.data == t_ptr->data)
2850                         break;
2851         }
2852         RNA_property_collection_end(&iter);
2853         
2854         /* did we find it? */
2855         if (iter.valid)
2856                 return index;
2857         else
2858                 return -1;
2859 }
2860
2861 int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
2862 {
2863         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)rna_ensure_property(prop);
2864
2865         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2866
2867         if (cprop->lookupint) {
2868                 /* we have a callback defined, use it */
2869                 return cprop->lookupint(ptr, key, r_ptr);
2870         }
2871         else {
2872                 /* no callback defined, just iterate and find the nth item */
2873                 CollectionPropertyIterator iter;
2874                 int i;
2875
2876                 RNA_property_collection_begin(ptr, prop, &iter);
2877                 for (i = 0; iter.valid; RNA_property_collection_next(&iter), i++) {
2878                         if (i == key) {
2879                                 *r_ptr = iter.ptr;
2880                                 break;
2881                         }
2882                 }
2883                 RNA_property_collection_end(&iter);
2884
2885                 if (!iter.valid)
2886                         memset(r_ptr, 0, sizeof(*r_ptr));
2887
2888                 return iter.valid;
2889         }
2890 }
2891
2892 int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
2893 {
2894         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)rna_ensure_property(prop);
2895
2896         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2897
2898         if (cprop->lookupstring) {
2899                 /* we have a callback defined, use it */
2900                 return cprop->lookupstring(ptr, key, r_ptr);
2901         }
2902         else {
2903                 /* no callback defined, compare with name properties if they exist */
2904                 CollectionPropertyIterator iter;
2905                 PropertyRNA *nameprop;
2906                 char name[256], *nameptr;
2907                 int found = 0;
2908                 int keylen = strlen(key);
2909                 int namelen;
2910
2911                 RNA_property_collection_begin(ptr, prop, &iter);
2912                 for (; iter.valid; RNA_property_collection_next(&iter)) {
2913                         if (iter.ptr.data && iter.ptr.type->nameproperty) {
2914                                 nameprop = iter.ptr.type->nameproperty;
2915
2916                                 nameptr = RNA_property_string_get_alloc(&iter.ptr, nameprop, name, sizeof(name), &namelen);
2917
2918                                 if ((keylen == namelen) && (strcmp(nameptr, key) == 0)) {
2919                                         *r_ptr = iter.ptr;
2920                                         found = 1;
2921                                 }
2922
2923                                 if ((char *)&name != nameptr)
2924                                         MEM_freeN(nameptr);
2925
2926                                 if (found)
2927                                         break;
2928                         }
2929                 }
2930                 RNA_property_collection_end(&iter);
2931
2932                 if (!iter.valid)
2933                         memset(r_ptr, 0, sizeof(*r_ptr));
2934
2935                 return iter.valid;
2936         }
2937 }
2938
2939 /* zero return is an assignment error */
2940 int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
2941 {
2942         CollectionPropertyRNA *cprop = (CollectionPropertyRNA*)rna_ensure_property(prop);
2943
2944         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2945
2946         if (cprop->assignint) {
2947                 /* we have a callback defined, use it */
2948                 return cprop->assignint(ptr, key, assign_ptr);
2949         }
2950
2951         return 0;
2952 }
2953
2954 int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
2955 {
2956         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2957
2958         *r_ptr = *ptr;
2959         return ((r_ptr->type = rna_ensure_property(prop)->srna) ? 1:0);
2960 }
2961
2962 int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array)
2963 {
2964         CollectionPropertyIterator iter;
2965         ArrayIterator *internal;
2966         char *arrayp;
2967
2968         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
2969
2970         if (!(prop->flag & PROP_RAW_ARRAY) || !(itemprop->flag & PROP_RAW_ACCESS))
2971                 return 0;
2972
2973         RNA_property_collection_begin(ptr, prop, &iter);
2974
2975         if (iter.valid) {
2976                 /* get data from array iterator and item property */
2977                 internal = iter.internal;
2978                 arrayp = (iter.valid)? iter.ptr.data: NULL;
2979
2980                 if (internal->skip || !RNA_property_editable(&iter.ptr, itemprop)) {
2981                         /* we might skip some items, so it's not a proper array */
2982                         RNA_property_collection_end(&iter);
2983                         return 0;
2984                 }
2985
2986                 array->array = arrayp + itemprop->rawoffset;
2987                 array->stride = internal->itemsize;
2988                 array->len = ((char*)internal->endptr - arrayp)/internal->itemsize;
2989                 array->type = itemprop->rawtype;
2990         }
2991         else
2992                 memset(array, 0, sizeof(RawArray));
2993
2994         RNA_property_collection_end(&iter);
2995
2996         return 1;
2997 }
2998
2999 #define RAW_GET(dtype, var, raw, a)                                           \
3000 {                                                                             \
3001         switch (raw.type) {                                                        \
3002                 case PROP_RAW_CHAR: var = (dtype)((char*)raw.array)[a]; break;        \
3003                 case PROP_RAW_SHORT: var = (dtype)((short*)raw.array)[a]; break;      \
3004                 case PROP_RAW_INT: var = (dtype)((int*)raw.array)[a]; break;          \
3005                 case PROP_RAW_FLOAT: var = (dtype)((float*)raw.array)[a]; break;      \
3006                 case PROP_RAW_DOUBLE: var = (dtype)((double*)raw.array)[a]; break;    \
3007                 default: var = (dtype)0;                                              \
3008         }                                                                         \
3009 }
3010
3011 #define RAW_SET(dtype, raw, a, var)                                           \
3012 {                                                                             \
3013         switch (raw.type) {                                                        \
3014                 case PROP_RAW_CHAR: ((char*)raw.array)[a] = (char)var; break;         \
3015                 case PROP_RAW_SHORT: ((short*)raw.array)[a] = (short)var; break;      \
3016                 case PROP_RAW_INT: ((int*)raw.array)[a] = (int)var; break;            \
3017                 case PROP_RAW_FLOAT: ((float*)raw.array)[a] = (float)var; break;      \
3018                 case PROP_RAW_DOUBLE: ((double*)raw.array)[a] = (double)var; break;   \
3019                 default: break;                                                       \
3020         }                                                                         \
3021 }
3022
3023 int RNA_raw_type_sizeof(RawPropertyType type)
3024 {
3025         switch (type) {
3026                 case PROP_RAW_CHAR: return sizeof(char);
3027                 case PROP_RAW_SHORT: return sizeof(short);
3028                 case PROP_RAW_INT: return sizeof(int);
3029                 case PROP_RAW_FLOAT: return sizeof(float);
3030                 case PROP_RAW_DOUBLE: return sizeof(double);
3031                 default: return 0;
3032         }
3033 }
3034
3035 static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *prop, const char *propname, void *inarray, RawPropertyType intype, int inlen, int set)
3036 {
3037         StructRNA *ptype;
3038         PointerRNA itemptr;
3039         PropertyRNA *itemprop, *iprop;
3040         PropertyType itemtype = 0;
3041         RawArray in;
3042         int itemlen = 0;
3043
3044         /* initialize in array, stride assumed 0 in following code */
3045         in.array = inarray;
3046         in.type = intype;
3047         in.len = inlen;
3048         in.stride = 0;
3049
3050         ptype = RNA_property_pointer_type(ptr, prop);
3051
3052         /* try to get item property pointer */
3053         RNA_pointer_create(NULL, ptype, NULL, &itemptr);
3054         itemprop = RNA_struct_find_property(&itemptr, propname);
3055
3056         if (itemprop) {
3057                 /* we have item property pointer */
3058                 RawArray out;
3059
3060                 /* check type */
3061                 itemtype = RNA_property_type(itemprop);
3062
3063                 if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3064                         BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3065                         return 0;
3066                 }
3067
3068                 /* check item array */
3069                 itemlen = RNA_property_array_length(&itemptr, itemprop);
3070
3071                 /* try to access as raw array */
3072                 if (RNA_property_collection_raw_array(ptr, prop, itemprop, &out)) {
3073                         int arraylen = (itemlen == 0) ? 1 : itemlen;
3074                         if (in.len != arraylen*out.len) {
3075                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (expected %d, got %d)", out.len*arraylen, in.len);
3076                                 return 0;
3077                         }
3078                         
3079                         /* matching raw types */
3080                         if (out.type == in.type) {
3081                                 void *inp = in.array;
3082                                 void *outp = out.array;
3083                                 int a, size;
3084
3085                                 size = RNA_raw_type_sizeof(out.type) * arraylen;
3086
3087                                 for (a = 0; a<out.len; a++) {
3088                                         if (set) memcpy(outp, inp, size);
3089                                         else memcpy(inp, outp, size);
3090
3091                                         inp = (char*)inp + size;
3092                                         outp = (char*)outp + out.stride;
3093                                 }
3094
3095                                 return 1;
3096                         }
3097
3098                         /* could also be faster with non-matching types,
3099                          * for now we just do slower loop .. */
3100                 }
3101         }
3102
3103         {
3104                 void *tmparray = NULL;
3105                 int tmplen = 0;
3106                 int err = 0, j, a = 0;
3107                 int needconv = 1;
3108
3109                 if (((itemtype == PROP_BOOLEAN || itemtype == PROP_INT) && in.type == PROP_RAW_INT) ||
3110                         (itemtype == PROP_FLOAT && in.type == PROP_RAW_FLOAT))
3111                         /* avoid creating temporary buffer if the data type match */
3112                         needconv = 0;
3113
3114                 /* no item property pointer, can still be id property, or
3115                  * property of a type derived from the collection pointer type */
3116                 RNA_PROP_BEGIN(ptr, itemptr, prop) {
3117                         if (itemptr.data) {
3118                                 if (itemprop) {
3119                                         /* we got the property already */
3120                                         iprop = itemprop;
3121                                 }
3122                                 else {
3123                                         /* not yet, look it up and verify if it is valid */
3124                                         iprop = RNA_struct_find_property(&itemptr, propname);
3125
3126                                         if (iprop) {
3127                                                 itemlen = RNA_property_array_length(&itemptr, iprop);
3128                                                 itemtype = RNA_property_type(iprop);
3129                                         }
3130                                         else {
3131                                                 BKE_reportf(reports, RPT_ERROR, "Property named %s not found", propname);
3132                                                 err = 1;
3133                                                 break;
3134                                         }
3135
3136                                         if (!ELEM3(itemtype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
3137                                                 BKE_report(reports, RPT_ERROR, "Only boolean, int and float properties supported");
3138                                                 err = 1;
3139                                                 break;
3140                                         }
3141                                 }
3142
3143                                 /* editable check */
3144                                 if (!set || RNA_property_editable(&itemptr, iprop)) {
3145                                         if (a+itemlen > in.len) {
3146                                                 BKE_reportf(reports, RPT_ERROR, "Array length mismatch (got %d, expected more)", in.len);
3147                                                 err = 1;
3148                                                 break;
3149                                         }
3150
3151                                         if (itemlen == 0) {
3152                                                 /* handle conversions */
3153                                                 if (set) {
3154                                                         switch (itemtype) {
3155                                                                 case PROP_BOOLEAN: {
3156                                                                         int b;
3157                                                                         RAW_GET(int, b, in, a);
3158                                                                         RNA_property_boolean_set(&itemptr, iprop, b);
3159                                                                         break;
3160                                                                 }
3161                                                                 case PROP_INT: {
3162                                                                         int i;
3163                                                                         RAW_GET(int, i, in, a);
3164                                                                         RNA_property_int_set(&itemptr, iprop, i);
3165                                                                         break;
3166                                                                 }
3167                                                                 case PROP_FLOAT: {
3168                                                                         float f;
3169                                                                         RAW_GET(float, f, in, a);
3170                                                                         RNA_property_float_set(&itemptr, iprop, f);
3171                                                                         break;
3172                                                                 }
3173                                                                 default:
3174                                                                         break;
3175                                                         }
3176                                                 }
3177                                                 else {
3178                                                         switch (itemtype) {
3179                                                                 case PROP_BOOLEAN: {
3180                                                                         int b = RNA_property_boolean_get(&itemptr, iprop);
3181                                                                         RAW_SET(int, in, a, b);
3182                                                                         break;
3183                                                                 }
3184                                                                 case PROP_INT: {
3185                                                                         int i = RNA_property_int_get(&itemptr, iprop);
3186                                                                         RAW_SET(int, in, a, i);
3187                                                                         break;
3188                                                                 }
3189                                                                 case PROP_FLOAT: {
3190                                                                         float f = RNA_property_float_get(&itemptr, iprop);
3191                                                                         RAW_SET(float, in, a, f);
3192                                                                         break;
3193                                                                 }
3194                                                                 default:
3195                                                                         break;
3196                                                         }
3197                                                 }
3198                                                 a++;
3199                                         }
3200                                         else if (needconv == 1) {
3201                                                 /* allocate temporary array if needed */
3202                                                 if (tmparray && tmplen != itemlen) {
3203                                                         MEM_freeN(tmparray);
3204                                                         tmparray = NULL;
3205                                                 }
3206                                                 if (!tmparray) {
3207                                                         tmparray = MEM_callocN(sizeof(float)*itemlen, "RNA tmparray\n");
3208                                                         tmplen = itemlen;
3209                                                 }
3210
3211                                                 /* handle conversions */
3212                                                 if (set) {
3213                                                         switch (itemtype) {
3214                                                                 case PROP_BOOLEAN: {
3215                                                                         for (j = 0; j<itemlen; j++, a++)
3216                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
3217                                                                         RNA_property_boolean_set_array(&itemptr, iprop, tmparray);
3218                                                                         break;
3219                                                                 }
3220                                                                 case PROP_INT: {
3221                                                                         for (j = 0; j<itemlen; j++, a++)
3222                                                                                 RAW_GET(int, ((int*)tmparray)[j], in, a);
3223                                                                         RNA_property_int_set_array(&itemptr, iprop, tmparray);
3224                                                                         break;
3225                                                                 }
3226                                                                 case PROP_FLOAT: {
3227                                                                         for (j = 0; j<itemlen; j++, a++)
3228                                                                                 RAW_GET(float, ((float*)tmparray)[j], in, a);
3229                                                                         RNA_property_float_set_array(&itemptr, iprop, tmparray);
3230                                                                         break;
3231                                                                 }
3232                                                                 default:
3233                                                                         break;
3234                                                         }
3235                                                 }
3236                                                 else {
3237                                                         switch (itemtype) {
3238                                                                 case PROP_BOOLEAN: {
3239                                                                         RNA_property_boolean_get_array(&itemptr, iprop, tmparray);
3240                                                                         for (j = 0; j<itemlen; j++, a++)
3241                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
3242                                                                         break;
3243                                                                 }
3244                                                                 case PROP_INT: {
3245                                                                         RNA_property_int_get_array(&itemptr, iprop, tmparray);
3246                                                                         for (j = 0; j<itemlen; j++, a++)
3247                                                                                 RAW_SET(int, in, a, ((int*)tmparray)[j]);
3248                                                                         break;
3249                                                                 }
3250                                                                 case PROP_FLOAT: {
3251                                                                         RNA_property_float_get_array(&itemptr, iprop, tmparray);
3252                                                                         for (j = 0; j<itemlen; j++, a++)
3253                                                                                 RAW_SET(float, in, a, ((float*)tmparray)[j]);
3254                                                                         break;
3255                                                                 }
3256                                                                 default:
3257                                                                         break;
3258                                                         }
3259                                                 }
3260                                         }
3261                                         else {
3262                                                 if (set) {