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