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