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