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