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