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