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