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         if (p == NULL || p == identifier || p + len_sep >= identifier + len_id) {
876                 BKE_reportf(reports, RPT_ERROR, "'%s' doesn't contain '%s' with prefix & suffix", identifier, sep);
877                 return false;
878         }
879
880         const char *c, *start, *end, *last;
881         start = identifier;
882         end = p;
883         last = end - 1;
884         for (c = start; c != end; c++) {
885                 if (((*c >= 'A' && *c <= 'Z') ||
886                      ((c != start) && (*c >= '0' && *c <= '9')) ||
887                      ((c != start) && (c != last) && (*c == '_'))) == 0)
888                 {
889                         BKE_reportf(reports, RPT_ERROR, "'%s' doesn't have upper case alpha-numeric prefix", identifier);
890                         return false;
891                 }
892         }
893
894         start = p + len_sep;
895         end = identifier + len_id;
896         last = end - 1;
897         for (c = start; c != end; c++) {
898                 if (((*c >= 'A' && *c <= 'Z') ||
899                      (*c >= 'a' && *c <= 'z') ||
900                      (*c >= '0' && *c <= '9') ||
901                      ((c != start) && (c != last) && (*c == '_'))) == 0)
902                 {
903                         BKE_reportf(reports, RPT_ERROR, "'%s' doesn't have an alpha-numeric suffix", identifier);
904                         return false;
905                 }
906         }
907         return true;
908 }
909
910 /* Property Information */
911
912 const char *RNA_property_identifier(PropertyRNA *prop)
913 {
914         return rna_ensure_property_identifier(prop);
915 }
916
917 const char *RNA_property_description(PropertyRNA *prop)
918 {
919         return TIP_(rna_ensure_property_description(prop));
920 }
921
922 PropertyType RNA_property_type(PropertyRNA *prop)
923 {
924         return rna_ensure_property(prop)->type;
925 }
926
927 PropertySubType RNA_property_subtype(PropertyRNA *prop)
928 {
929         return rna_ensure_property(prop)->subtype;
930 }
931
932 PropertyUnit RNA_property_unit(PropertyRNA *prop)
933 {
934         return RNA_SUBTYPE_UNIT(rna_ensure_property(prop)->subtype);
935 }
936
937 int RNA_property_flag(PropertyRNA *prop)
938 {
939         return rna_ensure_property(prop)->flag;
940 }
941
942 bool RNA_property_builtin(PropertyRNA *prop)
943 {
944         return (rna_ensure_property(prop)->flag_internal & PROP_INTERN_BUILTIN) != 0;
945 }
946
947 void *RNA_property_py_data_get(PropertyRNA *prop)
948 {
949         return prop->py_data;
950 }
951
952 int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
953 {
954         return rna_ensure_property_array_length(ptr, prop);
955 }
956
957 bool RNA_property_array_check(PropertyRNA *prop)
958 {
959         return rna_ensure_property_array_check(prop);
960 }
961
962 /* used by BPY to make an array from the python object */
963 int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[])
964 {
965         PropertyRNA *rprop = rna_ensure_property(prop);
966
967         if (length)
968                 rna_ensure_property_multi_array_length(ptr, prop, length);
969
970         return rprop->arraydimension;
971 }
972
973 /* Return the size of Nth dimension. */
974 int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dim)
975 {
976         int len[RNA_MAX_ARRAY_DIMENSION];
977
978         rna_ensure_property_multi_array_length(ptr, prop, len);
979
980         return len[dim];
981 }
982
983 char RNA_property_array_item_char(PropertyRNA *prop, int index)
984 {
985         const char *vectoritem = "XYZW";
986         const char *quatitem = "WXYZ";
987         const char *coloritem = "RGBA";
988         PropertySubType subtype = rna_ensure_property(prop)->subtype;
989
990         BLI_assert(index >= 0);
991
992         /* get string to use for array index */
993         if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
994                 return quatitem[index];
995         }
996         else if ((index < 4) && ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
997                                      PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION, PROP_COORDS))
998         {
999                 return vectoritem[index];
1000         }
1001         else if ((index < 4) && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1002                 return coloritem[index];
1003         }
1004
1005         return '\0';
1006 }
1007
1008 int RNA_property_array_item_index(PropertyRNA *prop, char name)
1009 {
1010         PropertySubType subtype = rna_ensure_property(prop)->subtype;
1011
1012         /* get index based on string name/alias */
1013         /* maybe a function to find char index in string would be better than all the switches */
1014         if (ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) {
1015                 switch (name) {
1016                         case 'w':
1017                                 return 0;
1018                         case 'x':
1019                                 return 1;
1020                         case 'y':
1021                                 return 2;
1022                         case 'z':
1023                                 return 3;
1024                 }
1025         }
1026         else if (ELEM(subtype, PROP_TRANSLATION, PROP_DIRECTION, PROP_XYZ, PROP_XYZ_LENGTH,
1027                        PROP_EULER, PROP_VELOCITY, PROP_ACCELERATION))
1028         {
1029                 switch (name) {
1030                         case 'x':
1031                                 return 0;
1032                         case 'y':
1033                                 return 1;
1034                         case 'z':
1035                                 return 2;
1036                         case 'w':
1037                                 return 3;
1038                 }
1039         }
1040         else if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA)) {
1041                 switch (name) {
1042                         case 'r':
1043                                 return 0;
1044                         case 'g':
1045                                 return 1;
1046                         case 'b':
1047                                 return 2;
1048                         case 'a':
1049                                 return 3;
1050                 }
1051         }
1052
1053         return -1;
1054 }
1055
1056
1057 void RNA_property_int_range(PointerRNA *ptr, PropertyRNA *prop, int *hardmin, int *hardmax)
1058 {
1059         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1060         int softmin, softmax;
1061
1062         if (prop->magic != RNA_MAGIC) {
1063                 /* attempt to get the local ID values */
1064                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1065
1066                 if (idp_ui) {
1067                         IDProperty *item;
1068
1069                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_INT);
1070                         *hardmin = item ? IDP_Int(item) : INT_MIN;
1071
1072                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_INT);
1073                         *hardmax = item ? IDP_Int(item) : INT_MAX;
1074
1075                         return;
1076                 }
1077         }
1078
1079         if (iprop->range) {
1080                 *hardmin = INT_MIN;
1081                 *hardmax = INT_MAX;
1082
1083                 iprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1084         }
1085         else if (iprop->range_ex) {
1086                 *hardmin = INT_MIN;
1087                 *hardmax = INT_MAX;
1088
1089                 iprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1090         }
1091         else {
1092                 *hardmin = iprop->hardmin;
1093                 *hardmax = iprop->hardmax;
1094         }
1095 }
1096
1097 void RNA_property_int_ui_range(PointerRNA *ptr, PropertyRNA *prop, int *softmin, int *softmax, int *step)
1098 {
1099         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
1100         int hardmin, hardmax;
1101         
1102         if (prop->magic != RNA_MAGIC) {
1103                 /* attempt to get the local ID values */
1104                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1105
1106                 if (idp_ui) {
1107                         IDProperty *item;
1108
1109                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_INT);
1110                         *softmin = item ? IDP_Int(item) : INT_MIN;
1111
1112                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_INT);
1113                         *softmax = item ? IDP_Int(item) : INT_MAX;
1114
1115                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_INT);
1116                         *step = item ? IDP_Int(item) : 1;
1117
1118                         return;
1119                 }
1120         }
1121
1122         *softmin = iprop->softmin;
1123         *softmax = iprop->softmax;
1124
1125         if (iprop->range) {
1126                 hardmin = INT_MIN;
1127                 hardmax = INT_MAX;
1128
1129                 iprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1130
1131                 *softmin = max_ii(*softmin, hardmin);
1132                 *softmax = min_ii(*softmax, hardmax);
1133         }
1134         else if (iprop->range_ex) {
1135                 hardmin = INT_MIN;
1136                 hardmax = INT_MAX;
1137
1138                 iprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1139
1140                 *softmin = max_ii(*softmin, hardmin);
1141                 *softmax = min_ii(*softmax, hardmax);
1142         }
1143
1144         *step = iprop->step;
1145 }
1146
1147 void RNA_property_float_range(PointerRNA *ptr, PropertyRNA *prop, float *hardmin, float *hardmax)
1148 {
1149         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1150         float softmin, softmax;
1151
1152         if (prop->magic != RNA_MAGIC) {
1153                 /* attempt to get the local ID values */
1154                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1155
1156                 if (idp_ui) {
1157                         IDProperty *item;
1158
1159                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "min", IDP_DOUBLE);
1160                         *hardmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1161
1162                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "max", IDP_DOUBLE);
1163                         *hardmax = item ? (float)IDP_Double(item) : FLT_MAX;
1164
1165                         return;
1166                 }
1167         }
1168
1169         if (fprop->range) {
1170                 *hardmin = -FLT_MAX;
1171                 *hardmax = FLT_MAX;
1172
1173                 fprop->range(ptr, hardmin, hardmax, &softmin, &softmax);
1174         }
1175         else if (fprop->range_ex) {
1176                 *hardmin = -FLT_MAX;
1177                 *hardmax = FLT_MAX;
1178
1179                 fprop->range_ex(ptr, prop, hardmin, hardmax, &softmin, &softmax);
1180         }
1181         else {
1182                 *hardmin = fprop->hardmin;
1183                 *hardmax = fprop->hardmax;
1184         }
1185 }
1186
1187 void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *softmin, float *softmax,
1188                                  float *step, float *precision)
1189 {
1190         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
1191         float hardmin, hardmax;
1192
1193         if (prop->magic != RNA_MAGIC) {
1194                 /* attempt to get the local ID values */
1195                 IDProperty *idp_ui = rna_idproperty_ui(prop);
1196
1197                 if (idp_ui) {
1198                         IDProperty *item;
1199
1200                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_min", IDP_DOUBLE);
1201                         *softmin = item ? (float)IDP_Double(item) : -FLT_MAX;
1202
1203                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "soft_max", IDP_DOUBLE);
1204                         *softmax = item ? (float)IDP_Double(item) : FLT_MAX;
1205
1206                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "step", IDP_DOUBLE);
1207                         *step = item ? (float)IDP_Double(item) : 1.0f;
1208
1209                         item = IDP_GetPropertyTypeFromGroup(idp_ui, "precision", IDP_DOUBLE);
1210                         *precision = item ? (float)IDP_Double(item) : 3.0f;
1211
1212                         return;
1213                 }
1214         }
1215
1216         *softmin = fprop->softmin;
1217         *softmax = fprop->softmax;
1218
1219         if (fprop->range) {
1220                 hardmin = -FLT_MAX;
1221                 hardmax = FLT_MAX;
1222
1223                 fprop->range(ptr, &hardmin, &hardmax, softmin, softmax);
1224
1225                 *softmin = max_ff(*softmin, hardmin);
1226                 *softmax = min_ff(*softmax, hardmax);
1227         }
1228         else if (fprop->range_ex) {
1229                 hardmin = -FLT_MAX;
1230                 hardmax = FLT_MAX;
1231
1232                 fprop->range_ex(ptr, prop, &hardmin, &hardmax, softmin, softmax);
1233
1234                 *softmin = max_ff(*softmin, hardmin);
1235                 *softmax = min_ff(*softmax, hardmax);
1236         }
1237
1238         *step = fprop->step;
1239         *precision = (float)fprop->precision;
1240 }
1241
1242 int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value)
1243 {
1244         float min, max;
1245
1246         RNA_property_float_range(ptr, prop, &min, &max);
1247
1248         if (*value < min) {
1249                 *value = min;
1250                 return -1;
1251         }
1252         else if (*value > max) {
1253                 *value = max;
1254                 return 1;
1255         }
1256         else {
1257                 return 0;
1258         }
1259 }
1260
1261 int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value)
1262 {
1263         int min, max;
1264
1265         RNA_property_int_range(ptr, prop, &min, &max);
1266
1267         if (*value < min) {
1268                 *value = min;
1269                 return -1;
1270         }
1271         else if (*value > max) {
1272                 *value = max;
1273                 return 1;
1274         }
1275         else {
1276                 return 0;
1277         }
1278 }
1279
1280 /* this is the max length including \0 terminator.
1281  * '0' used when their is no maximum */
1282 int RNA_property_string_maxlength(PropertyRNA *prop)
1283 {
1284         StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
1285         return sprop->maxlength;
1286 }
1287
1288 StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
1289 {
1290         prop = rna_ensure_property(prop);
1291
1292         if (prop->type == PROP_POINTER) {
1293                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1294
1295                 if (pprop->typef)
1296                         return pprop->typef(ptr);
1297                 else if (pprop->type)
1298                         return pprop->type;
1299         }
1300         else if (prop->type == PROP_COLLECTION) {
1301                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
1302
1303                 if (cprop->item_type)
1304                         return cprop->item_type;
1305         }
1306         /* ignore other types, RNA_struct_find_nested calls with unchecked props */
1307
1308         return &RNA_UnknownType;
1309 }
1310
1311 int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value)
1312 {
1313         prop = rna_ensure_property(prop);
1314
1315         if (prop->type == PROP_POINTER) {
1316                 PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
1317
1318                 if (pprop->poll) {
1319                         if (rna_idproperty_check(&prop, ptr)) {
1320                                 return ((PropPointerPollFuncPy) pprop->poll)(ptr, *value, prop);
1321                         }
1322                         else {
1323                                 return pprop->poll(ptr, *value);
1324                         }
1325                 }
1326
1327                 return 1;
1328         }
1329
1330         printf("%s: %s is not a pointer property.\n", __func__, prop->identifier);
1331         return 0;
1332 }
1333
1334 /* Reuse for dynamic types  */
1335 EnumPropertyItem DummyRNA_NULL_items[] = {
1336         {0, NULL, 0, NULL, NULL}
1337 };
1338
1339 /* Reuse for dynamic types with default value */
1340 EnumPropertyItem DummyRNA_DEFAULT_items[] = {
1341         {0, "DEFAULT", 0, "Default", ""},
1342         {0, NULL, 0, NULL, NULL}
1343 };
1344
1345 void RNA_property_enum_items_ex(
1346         bContext *C, PointerRNA *ptr, PropertyRNA *prop, const bool use_static,
1347         EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1348 {
1349         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1350
1351         *r_free = false;
1352
1353         if (!use_static && eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1354                 EnumPropertyItem *item;
1355
1356                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1357                         item = eprop->itemf(NULL, ptr, prop, r_free);
1358                 else
1359                         item = eprop->itemf(C, ptr, prop, r_free);
1360
1361                 /* any callbacks returning NULL should be fixed */
1362                 BLI_assert(item != NULL);
1363
1364                 if (r_totitem) {
1365                         int tot;
1366                         for (tot = 0; item[tot].identifier; tot++) {
1367                                 /* pass */
1368                         }
1369                         *r_totitem = tot;
1370                 }
1371
1372                 *r_item = item;
1373         }
1374         else {
1375                 *r_item = eprop->item;
1376                 if (r_totitem)
1377                         *r_totitem = eprop->totitem;
1378         }
1379 }
1380
1381 void RNA_property_enum_items(
1382         bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1383 {
1384         RNA_property_enum_items_ex(C, ptr, prop, false, r_item, r_totitem, r_free);
1385 }
1386
1387 #ifdef WITH_INTERNATIONAL
1388 static void property_enum_translate(PropertyRNA *prop, EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1389 {
1390         if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1391                 int i;
1392
1393                 /* Note: Only do those tests once, and then use BLT_pgettext. */
1394                 bool do_iface = BLT_translate_iface();
1395                 bool do_tooltip = BLT_translate_tooltips();
1396                 EnumPropertyItem *nitem;
1397
1398                 if (!(do_iface || do_tooltip))
1399                         return;
1400
1401                 if (*r_free) {
1402                         nitem = *r_item;
1403                 }
1404                 else {
1405                         EnumPropertyItem *item = *r_item;
1406                         int tot;
1407
1408                         if (r_totitem) {
1409                                 tot = *r_totitem;
1410                         }
1411                         else {
1412                                 /* count */
1413                                 for (tot = 0; item[tot].identifier; tot++) {
1414                                         /* pass */
1415                                 }
1416                         }
1417
1418                         nitem = MEM_mallocN(sizeof(EnumPropertyItem) * (tot + 1), "enum_items_gettexted");
1419                         memcpy(nitem, item, sizeof(EnumPropertyItem) * (tot + 1));
1420
1421                         *r_free = true;
1422                 }
1423
1424                 for (i = 0; nitem[i].identifier; i++) {
1425                         if (nitem[i].name && do_iface) {
1426                                 nitem[i].name = BLT_pgettext(prop->translation_context, nitem[i].name);
1427                         }
1428                         if (nitem[i].description && do_tooltip) {
1429                                 nitem[i].description = BLT_pgettext(NULL, nitem[i].description);
1430                         }
1431                 }
1432
1433                 *r_item = nitem;
1434         }
1435 }
1436 #endif
1437
1438 void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1439                                        EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1440 {
1441         RNA_property_enum_items(C, ptr, prop, r_item, r_totitem, r_free);
1442
1443 #ifdef WITH_INTERNATIONAL
1444         property_enum_translate(prop, r_item, r_totitem, r_free);
1445 #endif
1446 }
1447
1448 void RNA_property_enum_items_gettexted_all(bContext *C, PointerRNA *ptr, PropertyRNA *prop,
1449                                        EnumPropertyItem **r_item, int *r_totitem, bool *r_free)
1450 {
1451         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
1452         int mem_size = sizeof(EnumPropertyItem) * (eprop->totitem + 1);
1453         /* first return all items */
1454         *r_free = true;
1455         *r_item = MEM_mallocN(mem_size, "enum_gettext_all");
1456          memcpy(*r_item, eprop->item, mem_size);
1457
1458         if (r_totitem)
1459                 *r_totitem = eprop->totitem;
1460
1461         if (eprop->itemf && (C != NULL || (prop->flag & PROP_ENUM_NO_CONTEXT))) {
1462                 EnumPropertyItem *item;
1463                 int i;
1464                 bool free = false;
1465
1466                 if (prop->flag & PROP_ENUM_NO_CONTEXT)
1467                         item = eprop->itemf(NULL, ptr, prop, &free);
1468                 else
1469                         item = eprop->itemf(C, ptr, prop, &free);
1470
1471                 /* any callbacks returning NULL should be fixed */
1472                 BLI_assert(item != NULL);
1473
1474                 for (i = 0; i < eprop->totitem; i++) {
1475                         bool exists = false;
1476                         int i_fixed;
1477
1478                         /* items that do not exist on list are returned, but have their names/identifiers NULLed out */
1479                         for (i_fixed = 0; item[i_fixed].identifier; i_fixed++) {
1480                                 if (STREQ(item[i_fixed].identifier, (*r_item)[i].identifier)) {
1481                                         exists = true;
1482                                         break;
1483                                 }
1484                         }
1485
1486                         if (!exists) {
1487                                 (*r_item)[i].name = NULL;
1488                                 (*r_item)[i].identifier = "";
1489                         }
1490                 }
1491
1492                 if (free)
1493                         MEM_freeN(item);
1494         }
1495
1496 #ifdef WITH_INTERNATIONAL
1497         property_enum_translate(prop, r_item, r_totitem, r_free);
1498 #endif
1499 }
1500
1501 bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value)
1502 {
1503         EnumPropertyItem *item;
1504         bool free;
1505         bool found;
1506
1507         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1508
1509         if (item) {
1510                 const int i = RNA_enum_from_identifier(item, identifier);
1511                 if (i != -1) {
1512                         *r_value = item[i].value;
1513                         found = true;
1514                 }
1515                 else {
1516                         found = false;
1517                 }
1518
1519                 if (free) {
1520                         MEM_freeN(item);
1521                 }
1522         }
1523         else {
1524                 found = false;
1525         }
1526         return found;
1527 }
1528
1529 bool RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **r_identifier)
1530 {
1531         const int i = RNA_enum_from_value(item, value);
1532         if (i != -1) {
1533                 *r_identifier = item[i].identifier;
1534                 return true;
1535         }
1536         else {
1537                 return false;
1538         }
1539 }
1540
1541 int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **r_identifier)
1542 {
1543         int index = 0;
1544         for (; item->identifier; item++) {
1545                 if (item->identifier[0] && item->value & value) {
1546                         r_identifier[index++] = item->identifier;
1547                 }
1548         }
1549         r_identifier[index] = NULL;
1550         return index;
1551 }
1552
1553 bool RNA_enum_name(EnumPropertyItem *item, const int value, const char **r_name)
1554 {
1555         const int i = RNA_enum_from_value(item, value);
1556         if (i != -1) {
1557                 *r_name = item[i].name;
1558                 return true;
1559         }
1560         else {
1561                 return false;
1562         }
1563 }
1564
1565 bool RNA_enum_description(EnumPropertyItem *item, const int value, const char **r_description)
1566 {
1567         const int i = RNA_enum_from_value(item, value);
1568         if (i != -1) {
1569                 *r_description = item[i].description;
1570                 return true;
1571         }
1572         else {
1573                 return false;
1574         }
1575 }
1576
1577 int RNA_enum_from_identifier(EnumPropertyItem *item, const char *identifier)
1578 {
1579         int i = 0;
1580         for (; item->identifier; item++, i++) {
1581                 if (item->identifier[0] && STREQ(item->identifier, identifier)) {
1582                         return i;
1583                 }
1584         }
1585         return -1;
1586 }
1587
1588 int RNA_enum_from_value(EnumPropertyItem *item, const int value)
1589 {
1590         int i = 0;
1591         for (; item->identifier; item++, i++) {
1592                 if (item->identifier[0] && item->value == value) {
1593                         return i;
1594                 }
1595         }
1596         return -1;
1597 }
1598
1599 bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1600                                   const char **identifier)
1601 {
1602         EnumPropertyItem *item = NULL;
1603         bool free;
1604         
1605         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1606         if (item) {
1607                 bool result;
1608                 result = RNA_enum_identifier(item, value, identifier);
1609                 if (free)
1610                         MEM_freeN(item);
1611
1612                 return result;
1613         }
1614         return false;
1615 }
1616
1617 bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1618 {
1619         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_name(item, value, name);
1626                 if (free)
1627                         MEM_freeN(item);
1628                 
1629                 return result;
1630         }
1631         return false;
1632 }
1633
1634 bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name)
1635 {
1636         bool result;
1637
1638         result = RNA_property_enum_name(C, ptr, prop, value, name);
1639
1640         if (result) {
1641                 if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1642                         if (BLT_translate_iface()) {
1643                                 *name = BLT_pgettext(prop->translation_context, *name);
1644                         }
1645                 }
1646         }
1647
1648         return result;
1649 }
1650
1651 bool RNA_property_enum_item_from_value(
1652         bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1653         EnumPropertyItem *r_item)
1654 {
1655         EnumPropertyItem *item = NULL;
1656         bool free;
1657
1658         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1659         if (item) {
1660                 const int i = RNA_enum_from_value(item, value);
1661                 bool result;
1662
1663                 if (i != -1) {
1664                         *r_item = item[i];
1665                         result = true;
1666                 }
1667                 else {
1668                         result = false;
1669                 }
1670
1671                 if (free)
1672                         MEM_freeN(item);
1673
1674                 return result;
1675         }
1676         return false;
1677 }
1678
1679 bool RNA_property_enum_item_from_value_gettexted(
1680         bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1681         EnumPropertyItem *r_item)
1682 {
1683         bool result;
1684
1685         result = RNA_property_enum_item_from_value(C, ptr, prop, value, r_item);
1686
1687         if (!(prop->flag & PROP_ENUM_NO_TRANSLATE)) {
1688                 if (BLT_translate_iface()) {
1689                         r_item->name = BLT_pgettext(prop->translation_context, r_item->name);
1690                 }
1691         }
1692
1693         return result;
1694 }
1695
1696 int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value,
1697                                           const char **identifier)
1698 {
1699         EnumPropertyItem *item = NULL;
1700         bool free;
1701
1702         RNA_property_enum_items(C, ptr, prop, &item, NULL, &free);
1703         if (item) {
1704                 int result;
1705                 result = RNA_enum_bitflag_identifiers(item, value, identifier);
1706                 if (free)
1707                         MEM_freeN(item);
1708
1709                 return result;
1710         }
1711         return 0;
1712 }
1713
1714 const char *RNA_property_ui_name(PropertyRNA *prop)
1715 {
1716         return CTX_IFACE_(prop->translation_context, rna_ensure_property_name(prop));
1717 }
1718
1719 const char *RNA_property_ui_name_raw(PropertyRNA *prop)
1720 {
1721         return rna_ensure_property_name(prop);
1722 }
1723
1724 const char *RNA_property_ui_description(PropertyRNA *prop)
1725 {
1726         return TIP_(rna_ensure_property_description(prop));
1727 }
1728
1729 const char *RNA_property_ui_description_raw(PropertyRNA *prop)
1730 {
1731         return rna_ensure_property_description(prop);
1732 }
1733
1734 const char *RNA_property_translation_context(PropertyRNA *_prop)
1735 {
1736         PropertyRNA *prop = rna_ensure_property(_prop);
1737         return prop->translation_context;
1738 }
1739
1740 int RNA_property_ui_icon(PropertyRNA *prop)
1741 {
1742         return rna_ensure_property(prop)->icon;
1743 }
1744
1745 bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
1746 {
1747         ID *id = ptr->id.data;
1748         int flag;
1749         const char *dummy_info;
1750
1751         prop = rna_ensure_property(prop);
1752         flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
1753
1754         return ((flag & PROP_EDITABLE) &&
1755                 (flag & PROP_REGISTER) == 0 &&
1756                 (!id || !ID_IS_LINKED_DATABLOCK(id) || (prop->flag & PROP_LIB_EXCEPTION)));
1757 }
1758
1759 /**
1760  * Version of #RNA_property_editable that tries to return additional info in \a r_info that can be exposed in UI.
1761  */
1762 bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
1763 {
1764         ID *id = ptr->id.data;
1765         int flag;
1766
1767         prop = rna_ensure_property(prop);
1768         *r_info = "";
1769
1770         /* get flag */
1771         if (prop->editable) {
1772                 flag = prop->editable(ptr, r_info);
1773         }
1774         else {
1775                 flag = prop->flag;
1776                 if ((flag & PROP_EDITABLE) == 0 || (flag & PROP_REGISTER)) {
1777                         *r_info = "This property is for internal use only and can't be edited.";
1778                 }
1779         }
1780
1781         /* property from linked data-block */
1782         if (id && ID_IS_LINKED_DATABLOCK(id) && (prop->flag & PROP_LIB_EXCEPTION) == 0) {
1783                 if (!(*r_info)[0]) {
1784                         *r_info = "Can't edit this property from a linked data-block.";
1785                 }
1786                 return false;
1787         }
1788
1789         return ((flag & PROP_EDITABLE) && (flag & PROP_REGISTER) == 0);
1790 }
1791
1792 bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
1793 {
1794         int flag;
1795         const char *dummy_info;
1796
1797         prop = rna_ensure_property(prop);
1798         flag = prop->editable ? prop->editable(ptr, &dummy_info) : prop->flag;
1799         return (flag & PROP_EDITABLE) != 0;
1800 }
1801
1802 /* same as RNA_property_editable(), except this checks individual items in an array */
1803 bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
1804 {
1805         ID *id;
1806         int flag;
1807
1808         BLI_assert(index >= 0);
1809
1810         prop = rna_ensure_property(prop);
1811
1812         flag = prop->flag;
1813
1814         if (prop->editable) {
1815                 const char *dummy_info;
1816                 flag &= prop->editable(ptr, &dummy_info);
1817         }
1818
1819         if (prop->itemeditable)
1820                 flag &= prop->itemeditable(ptr, index);
1821
1822         id = ptr->id.data;
1823
1824         return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED_DATABLOCK(id) || (prop->flag & PROP_LIB_EXCEPTION));
1825 }
1826
1827 bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
1828 {
1829         /* check that base ID-block can support animation data */
1830         if (!id_can_have_animdata(ptr->id.data))
1831                 return false;
1832         
1833         prop = rna_ensure_property(prop);
1834
1835         if (!(prop->flag & PROP_ANIMATABLE))
1836                 return false;
1837
1838         return (prop->flag & PROP_EDITABLE) != 0;
1839 }
1840
1841 bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
1842 {
1843         int len = 1, index;
1844         bool driven, special;
1845
1846         if (!prop)
1847                 return false;
1848
1849         if (RNA_property_array_check(prop))
1850                 len = RNA_property_array_length(ptr, prop);
1851
1852         for (index = 0; index < len; index++) {
1853                 if (rna_get_fcurve(ptr, prop, index, NULL, NULL, &driven, &special))
1854                         return true;
1855         }
1856
1857         return false;
1858 }
1859
1860 /* this function is to check if its possible to create a valid path from the ID
1861  * its slow so don't call in a loop */
1862 bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
1863 {
1864         char *path = RNA_path_from_ID_to_property(ptr, prop);
1865         bool ret = false;
1866
1867         if (path) {
1868                 PointerRNA id_ptr;
1869                 PointerRNA r_ptr;
1870                 PropertyRNA *r_prop;
1871
1872                 RNA_id_pointer_create(ptr->id.data, &id_ptr);
1873                 if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
1874                         ret = (prop == r_prop);
1875                 }
1876                 MEM_freeN(path);
1877         }
1878
1879         return ret;
1880 }
1881
1882
1883 static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1884 {
1885         const bool is_rna = (prop->magic == RNA_MAGIC);
1886         prop = rna_ensure_property(prop);
1887
1888         if (is_rna) {
1889                 if (prop->update) {
1890                         /* ideally no context would be needed for update, but there's some
1891                          * parts of the code that need it still, so we have this exception */
1892                         if (prop->flag & PROP_CONTEXT_UPDATE) {
1893                                 if (C) {
1894                                         if ((prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) == PROP_CONTEXT_PROPERTY_UPDATE) {
1895                                                 ((ContextPropUpdateFunc)prop->update)(C, ptr, prop);
1896                                         }
1897                                         else {
1898                                                 ((ContextUpdateFunc)prop->update)(C, ptr);
1899                                         }
1900                                 }
1901                         }
1902                         else
1903                                 prop->update(bmain, scene, ptr);
1904                 }
1905                 if (prop->noteflag)
1906                         WM_main_add_notifier(prop->noteflag, ptr->id.data);
1907         }
1908         
1909         if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
1910                 /* WARNING! This is so property drivers update the display!
1911                  * not especially nice  */
1912                 DEG_id_tag_update(ptr->id.data, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
1913                 WM_main_add_notifier(NC_WINDOW, NULL);
1914                 /* Not nice as well, but the only way to make sure material preview
1915                  * is updated with custom nodes.
1916                  */
1917                 if ((prop->flag & PROP_IDPROPERTY) != 0 &&
1918                     (ptr->id.data != NULL) &&
1919                     (GS(((ID *)ptr->id.data)->name) == ID_NT))
1920                 {
1921                         WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
1922                 }
1923         }
1924 }
1925
1926 /* must keep in sync with 'rna_property_update'
1927  * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE
1928  * but this isn't likely to be a performance problem. */
1929 bool RNA_property_update_check(PropertyRNA *prop)
1930 {
1931         return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag);
1932 }
1933
1934 void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
1935 {
1936         rna_property_update(C, CTX_data_main(C), CTX_data_scene(C), ptr, prop);
1937 }
1938
1939 void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, PropertyRNA *prop)
1940 {
1941         rna_property_update(NULL, bmain, scene, ptr, prop);
1942 }
1943
1944
1945 /* RNA Updates Cache ------------------------ */
1946 /* Overview of RNA Update cache system:
1947  *
1948  * RNA Update calls need to be cached in order to maintain reasonable performance
1949  * of the animation system (i.e. maintaining a somewhat interactive framerate)
1950  * while still allowing updates to be called (necessary in particular for modifier
1951  * property updates to actually work).
1952  *
1953  * The cache is structured with a dual-layer structure
1954  * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
1955  *        and most updates end up using just that anyways)
1956  * - L2 = Update functions to be called on those PointerRNA's
1957  */
1958
1959 /* cache element */
1960 typedef struct tRnaUpdateCacheElem {
1961         struct tRnaUpdateCacheElem *next, *prev;
1962         
1963         PointerRNA ptr;     /* L1 key - id as primary, data secondary/ignored? */
1964         ListBase L2Funcs;   /* L2 functions (LinkData<RnaUpdateFuncRef>) */
1965 } tRnaUpdateCacheElem;
1966
1967 /* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */
1968 static ListBase rna_updates_cache = {NULL, NULL};
1969
1970 /* ........................... */
1971
1972 void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
1973 {
1974         const bool is_rna = (prop->magic == RNA_MAGIC);
1975         tRnaUpdateCacheElem *uce = NULL;
1976         UpdateFunc fn = NULL;
1977         LinkData *ld;
1978         
1979         /* sanity check */
1980         if (NULL == ptr)
1981                 return;
1982                 
1983         prop = rna_ensure_property(prop);
1984         
1985         /* we can only handle update calls with no context args for now (makes animsys updates easier) */
1986         if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE))
1987                 return;
1988         fn = prop->update;
1989                 
1990         /* find cache element for which key matches... */
1991         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
1992                 /* just match by id only for now, since most update calls that we'll encounter only really care about this */
1993                 /* TODO: later, the cache might need to have some nesting on L1 to cope better
1994                  * with these problems + some tagging to indicate we need this */
1995                 if (uce->ptr.id.data == ptr->id.data)
1996                         break;
1997         }
1998         if (uce == NULL) {
1999                 /* create new instance */
2000                 uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem");
2001                 BLI_addtail(&rna_updates_cache, uce);
2002                 
2003                 /* copy pointer */
2004                 RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
2005         }
2006         
2007         /* check on the update func */
2008         for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2009                 /* stop on match - function already cached */
2010                 if (fn == ld->data)
2011                         return;
2012         }
2013         /* else... if still here, we need to add it */
2014         BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn));
2015 }
2016
2017 void RNA_property_update_cache_flush(Main *bmain, Scene *scene)
2018 {
2019         tRnaUpdateCacheElem *uce;
2020         
2021         /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */
2022         
2023         /* execute the cached updates */
2024         for (uce = rna_updates_cache.first; uce; uce = uce->next) {
2025                 LinkData *ld;
2026                 
2027                 for (ld = uce->L2Funcs.first; ld; ld = ld->next) {
2028                         UpdateFunc fn = (UpdateFunc)ld->data;
2029                         fn(bmain, scene, &uce->ptr);
2030                 }
2031         }
2032 }
2033
2034 void RNA_property_update_cache_free(void)
2035 {
2036         tRnaUpdateCacheElem *uce, *ucn;
2037         
2038         for (uce = rna_updates_cache.first; uce; uce = ucn) {
2039                 ucn = uce->next;
2040                 
2041                 /* free L2 cache */
2042                 BLI_freelistN(&uce->L2Funcs);
2043                 
2044                 /* remove self */
2045                 BLI_freelinkN(&rna_updates_cache, uce);
2046         }
2047 }
2048
2049 /* ---------------------------------------------------------------------- */
2050
2051 /* Property Data */
2052
2053 int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop)
2054 {
2055         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2056         IDProperty *idprop;
2057         int value;
2058
2059         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2060         BLI_assert(RNA_property_array_check(prop) == false);
2061
2062         if ((idprop = rna_idproperty_check(&prop, ptr)))
2063                 value = IDP_Int(idprop);
2064         else if (bprop->get)
2065                 value = bprop->get(ptr);
2066         else if (bprop->get_ex)
2067                 value = bprop->get_ex(ptr, prop);
2068         else
2069                 value = bprop->defaultvalue;
2070
2071         BLI_assert(ELEM(value, false, true));
2072
2073         return value;
2074 }
2075
2076 void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2077 {
2078         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2079         IDProperty *idprop;
2080
2081         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2082         BLI_assert(RNA_property_array_check(prop) == false);
2083         BLI_assert(ELEM(value, false, true));
2084
2085         /* just in case other values are passed */
2086         if (value) value = 1;
2087
2088         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2089                 IDP_Int(idprop) = value;
2090                 rna_idproperty_touch(idprop);
2091         }
2092         else if (bprop->set) {
2093                 bprop->set(ptr, value);
2094         }
2095         else if (bprop->set_ex) {
2096                 bprop->set_ex(ptr, prop, value);
2097         }
2098         else if (prop->flag & PROP_EDITABLE) {
2099                 IDPropertyTemplate val = {0};
2100                 IDProperty *group;
2101
2102                 val.i = value;
2103
2104                 group = RNA_struct_idprops(ptr, 1);
2105                 if (group)
2106                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2107         }
2108 }
2109
2110 void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2111 {
2112         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2113         IDProperty *idprop;
2114
2115         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2116         BLI_assert(RNA_property_array_check(prop) != false);
2117
2118         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2119                 if (prop->arraydimension == 0)
2120                         values[0] = RNA_property_boolean_get(ptr, prop);
2121                 else
2122                         memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2123         }
2124         else if (prop->arraydimension == 0)
2125                 values[0] = RNA_property_boolean_get(ptr, prop);
2126         else if (bprop->getarray)
2127                 bprop->getarray(ptr, values);
2128         else if (bprop->getarray_ex)
2129                 bprop->getarray_ex(ptr, prop, values);
2130         else if (bprop->defaultarray)
2131                 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
2132         else
2133                 memset(values, 0, sizeof(int) * prop->totarraylength);
2134 }
2135
2136 int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2137 {
2138         int tmp[RNA_MAX_ARRAY_LENGTH];
2139         int len = rna_ensure_property_array_length(ptr, prop);
2140         int value;
2141
2142         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2143         BLI_assert(RNA_property_array_check(prop) != false);
2144         BLI_assert(index >= 0);
2145         BLI_assert(index < len);
2146
2147         if (len <= RNA_MAX_ARRAY_LENGTH) {
2148                 RNA_property_boolean_get_array(ptr, prop, tmp);
2149                 value = tmp[index];
2150         }
2151         else {
2152                 int *tmparray;
2153
2154                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2155                 RNA_property_boolean_get_array(ptr, prop, tmparray);
2156                 value = tmparray[index];
2157                 MEM_freeN(tmparray);
2158         }
2159
2160         BLI_assert(ELEM(value, false, true));
2161
2162         return value;
2163 }
2164
2165 void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2166 {
2167         BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop;
2168         IDProperty *idprop;
2169
2170         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2171         BLI_assert(RNA_property_array_check(prop) != false);
2172
2173         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2174                 if (prop->arraydimension == 0)
2175                         IDP_Int(idprop) = values[0];
2176                 else
2177                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2178
2179                 rna_idproperty_touch(idprop);
2180         }
2181         else if (prop->arraydimension == 0)
2182                 RNA_property_boolean_set(ptr, prop, values[0]);
2183         else if (bprop->setarray)
2184                 bprop->setarray(ptr, values);
2185         else if (bprop->setarray_ex)
2186                 bprop->setarray_ex(ptr, prop, values);
2187         else if (prop->flag & PROP_EDITABLE) {
2188                 IDPropertyTemplate val = {0};
2189                 IDProperty *group;
2190
2191                 val.array.len = prop->totarraylength;
2192                 val.array.type = IDP_INT;
2193
2194                 group = RNA_struct_idprops(ptr, 1);
2195                 if (group) {
2196                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2197                         IDP_AddToGroup(group, idprop);
2198                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2199                 }
2200         }
2201 }
2202
2203 void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2204 {
2205         int tmp[RNA_MAX_ARRAY_LENGTH];
2206         int len = rna_ensure_property_array_length(ptr, prop);
2207
2208         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2209         BLI_assert(RNA_property_array_check(prop) != false);
2210         BLI_assert(index >= 0);
2211         BLI_assert(index < len);
2212         BLI_assert(ELEM(value, false, true));
2213
2214         if (len <= RNA_MAX_ARRAY_LENGTH) {
2215                 RNA_property_boolean_get_array(ptr, prop, tmp);
2216                 tmp[index] = value;
2217                 RNA_property_boolean_set_array(ptr, prop, tmp);
2218         }
2219         else {
2220                 int *tmparray;
2221
2222                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2223                 RNA_property_boolean_get_array(ptr, prop, tmparray);
2224                 tmparray[index] = value;
2225                 RNA_property_boolean_set_array(ptr, prop, tmparray);
2226                 MEM_freeN(tmparray);
2227         }
2228 }
2229
2230 int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2231 {
2232         BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2233
2234         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2235         BLI_assert(RNA_property_array_check(prop) == false);
2236         BLI_assert(ELEM(bprop->defaultvalue, false, true));
2237
2238         return bprop->defaultvalue;
2239 }
2240
2241 void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2242 {
2243         BoolPropertyRNA *bprop = (BoolPropertyRNA *)rna_ensure_property(prop);
2244         
2245         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2246         BLI_assert(RNA_property_array_check(prop) != false);
2247
2248         if (prop->arraydimension == 0)
2249                 values[0] = bprop->defaultvalue;
2250         else if (bprop->defaultarray)
2251                 memcpy(values, bprop->defaultarray, sizeof(int) * prop->totarraylength);
2252         else
2253                 memset(values, 0, sizeof(int) * prop->totarraylength);
2254 }
2255
2256 int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2257 {
2258         int tmp[RNA_MAX_ARRAY_LENGTH];
2259         int len = rna_ensure_property_array_length(ptr, prop);
2260
2261         BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN);
2262         BLI_assert(RNA_property_array_check(prop) != false);
2263         BLI_assert(index >= 0);
2264         BLI_assert(index < prop->totarraylength);
2265
2266         if (len <= RNA_MAX_ARRAY_LENGTH) {
2267                 RNA_property_boolean_get_default_array(ptr, prop, tmp);
2268                 return tmp[index];
2269         }
2270         else {
2271                 int *tmparray, value;
2272
2273                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2274                 RNA_property_boolean_get_default_array(ptr, prop, tmparray);
2275                 value = tmparray[index];
2276                 MEM_freeN(tmparray);
2277
2278                 return value;
2279         }
2280 }
2281
2282 int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop)
2283 {
2284         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2285         IDProperty *idprop;
2286
2287         BLI_assert(RNA_property_type(prop) == PROP_INT);
2288         BLI_assert(RNA_property_array_check(prop) == false);
2289
2290         if ((idprop = rna_idproperty_check(&prop, ptr)))
2291                 return IDP_Int(idprop);
2292         else if (iprop->get)
2293                 return iprop->get(ptr);
2294         else if (iprop->get_ex)
2295                 return iprop->get_ex(ptr, prop);
2296         else
2297                 return iprop->defaultvalue;
2298 }
2299
2300 void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2301 {
2302         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2303         IDProperty *idprop;
2304
2305         BLI_assert(RNA_property_type(prop) == PROP_INT);
2306         BLI_assert(RNA_property_array_check(prop) == false);
2307         /* useful to check on bad values but set function should clamp */
2308         /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */
2309
2310         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2311                 RNA_property_int_clamp(ptr, prop, &value);
2312                 IDP_Int(idprop) = value;
2313                 rna_idproperty_touch(idprop);
2314         }
2315         else if (iprop->set)
2316                 iprop->set(ptr, value);
2317         else if (iprop->set_ex)
2318                 iprop->set_ex(ptr, prop, value);
2319         else if (prop->flag & PROP_EDITABLE) {
2320                 IDPropertyTemplate val = {0};
2321                 IDProperty *group;
2322
2323                 RNA_property_int_clamp(ptr, prop, &value);
2324
2325                 val.i = value;
2326
2327                 group = RNA_struct_idprops(ptr, 1);
2328                 if (group)
2329                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
2330         }
2331 }
2332
2333 void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values)
2334 {
2335         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2336         IDProperty *idprop;
2337
2338         BLI_assert(RNA_property_type(prop) == PROP_INT);
2339         BLI_assert(RNA_property_array_check(prop) != false);
2340
2341         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2342                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2343                 if (prop->arraydimension == 0)
2344                         values[0] = RNA_property_int_get(ptr, prop);
2345                 else
2346                         memcpy(values, IDP_Array(idprop), sizeof(int) * idprop->len);
2347         }
2348         else if (prop->arraydimension == 0)
2349                 values[0] = RNA_property_int_get(ptr, prop);
2350         else if (iprop->getarray)
2351                 iprop->getarray(ptr, values);
2352         else if (iprop->getarray_ex)
2353                 iprop->getarray_ex(ptr, prop, values);
2354         else if (iprop->defaultarray)
2355                 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2356         else
2357                 memset(values, 0, sizeof(int) * prop->totarraylength);
2358 }
2359
2360 void RNA_property_int_get_array_range(PointerRNA *ptr, PropertyRNA *prop, int values[2])
2361 {
2362         const int array_len = RNA_property_array_length(ptr, prop);
2363
2364         if (array_len <= 0) {
2365                 values[0] = 0;
2366                 values[1] = 0;
2367         }
2368         else if (array_len == 1) {
2369                 RNA_property_int_get_array(ptr, prop, values);
2370                 values[1] = values[0];
2371         }
2372         else {
2373                 int arr_stack[32];
2374                 int *arr;
2375                 int i;
2376
2377                 if (array_len > 32) {
2378                         arr = MEM_mallocN(sizeof(int) * array_len, __func__);
2379                 }
2380                 else {
2381                         arr = arr_stack;
2382                 }
2383
2384                 RNA_property_int_get_array(ptr, prop, arr);
2385                 values[0] = values[1] = arr[0];
2386                 for (i = 1; i < array_len; i++) {
2387                         values[0] = MIN2(values[0], arr[i]);
2388                         values[1] = MAX2(values[1], arr[i]);
2389                 }
2390
2391                 if (arr != arr_stack) {
2392                         MEM_freeN(arr);
2393                 }
2394         }
2395 }
2396
2397 int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2398 {
2399         int tmp[RNA_MAX_ARRAY_LENGTH];
2400         int len = rna_ensure_property_array_length(ptr, prop);
2401
2402         BLI_assert(RNA_property_type(prop) == PROP_INT);
2403         BLI_assert(RNA_property_array_check(prop) != false);
2404         BLI_assert(index >= 0);
2405         BLI_assert(index < len);
2406
2407         if (len <= RNA_MAX_ARRAY_LENGTH) {
2408                 RNA_property_int_get_array(ptr, prop, tmp);
2409                 return tmp[index];
2410         }
2411         else {
2412                 int *tmparray, value;
2413
2414                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2415                 RNA_property_int_get_array(ptr, prop, tmparray);
2416                 value = tmparray[index];
2417                 MEM_freeN(tmparray);
2418
2419                 return value;
2420         }
2421 }
2422
2423 void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *values)
2424 {
2425         IntPropertyRNA *iprop = (IntPropertyRNA *)prop;
2426         IDProperty *idprop;
2427
2428         BLI_assert(RNA_property_type(prop) == PROP_INT);
2429         BLI_assert(RNA_property_array_check(prop) != false);
2430
2431         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2432                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2433                 if (prop->arraydimension == 0)
2434                         IDP_Int(idprop) = values[0];
2435                 else
2436                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2437
2438                 rna_idproperty_touch(idprop);
2439         }
2440         else if (prop->arraydimension == 0)
2441                 RNA_property_int_set(ptr, prop, values[0]);
2442         else if (iprop->setarray)
2443                 iprop->setarray(ptr, values);
2444         else if (iprop->setarray_ex)
2445                 iprop->setarray_ex(ptr, prop, values);
2446         else if (prop->flag & PROP_EDITABLE) {
2447                 IDPropertyTemplate val = {0};
2448                 IDProperty *group;
2449
2450                 /* TODO: RNA_property_int_clamp_array(ptr, prop, &value); */
2451
2452                 val.array.len = prop->totarraylength;
2453                 val.array.type = IDP_INT;
2454
2455                 group = RNA_struct_idprops(ptr, 1);
2456                 if (group) {
2457                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2458                         IDP_AddToGroup(group, idprop);
2459                         memcpy(IDP_Array(idprop), values, sizeof(int) * idprop->len);
2460                 }
2461         }
2462 }
2463
2464 void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int value)
2465 {
2466         int tmp[RNA_MAX_ARRAY_LENGTH];
2467         int len = rna_ensure_property_array_length(ptr, prop);
2468
2469         BLI_assert(RNA_property_type(prop) == PROP_INT);
2470         BLI_assert(RNA_property_array_check(prop) != false);
2471         BLI_assert(index >= 0);
2472         BLI_assert(index < len);
2473
2474         if (len <= RNA_MAX_ARRAY_LENGTH) {
2475                 RNA_property_int_get_array(ptr, prop, tmp);
2476                 tmp[index] = value;
2477                 RNA_property_int_set_array(ptr, prop, tmp);
2478         }
2479         else {
2480                 int *tmparray;
2481
2482                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2483                 RNA_property_int_get_array(ptr, prop, tmparray);
2484                 tmparray[index] = value;
2485                 RNA_property_int_set_array(ptr, prop, tmparray);
2486                 MEM_freeN(tmparray);
2487         }
2488 }
2489
2490 int RNA_property_int_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2491 {
2492         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2493         return iprop->defaultvalue;
2494 }
2495
2496 void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, int *values)
2497 {
2498         IntPropertyRNA *iprop = (IntPropertyRNA *)rna_ensure_property(prop);
2499         
2500         BLI_assert(RNA_property_type(prop) == PROP_INT);
2501         BLI_assert(RNA_property_array_check(prop) != false);
2502
2503         if (prop->arraydimension == 0)
2504                 values[0] = iprop->defaultvalue;
2505         else if (iprop->defaultarray)
2506                 memcpy(values, iprop->defaultarray, sizeof(int) * prop->totarraylength);
2507         else
2508                 memset(values, 0, sizeof(int) * prop->totarraylength);
2509 }
2510
2511 int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2512 {
2513         int tmp[RNA_MAX_ARRAY_LENGTH];
2514         int len = rna_ensure_property_array_length(ptr, prop);
2515
2516         BLI_assert(RNA_property_type(prop) == PROP_INT);
2517         BLI_assert(RNA_property_array_check(prop) != false);
2518         BLI_assert(index >= 0);
2519         BLI_assert(index < prop->totarraylength);
2520
2521         if (len <= RNA_MAX_ARRAY_LENGTH) {
2522                 RNA_property_int_get_default_array(ptr, prop, tmp);
2523                 return tmp[index];
2524         }
2525         else {
2526                 int *tmparray, value;
2527
2528                 tmparray = MEM_mallocN(sizeof(int) * len, __func__);
2529                 RNA_property_int_get_default_array(ptr, prop, tmparray);
2530                 value = tmparray[index];
2531                 MEM_freeN(tmparray);
2532
2533                 return value;
2534         }
2535 }
2536
2537 float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
2538 {
2539         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2540         IDProperty *idprop;
2541
2542         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2543         BLI_assert(RNA_property_array_check(prop) == false);
2544
2545         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2546                 if (idprop->type == IDP_FLOAT)
2547                         return IDP_Float(idprop);
2548                 else
2549                         return (float)IDP_Double(idprop);
2550         }
2551         else if (fprop->get)
2552                 return fprop->get(ptr);
2553         else if (fprop->get_ex)
2554                 return fprop->get_ex(ptr, prop);
2555         else
2556                 return fprop->defaultvalue;
2557 }
2558
2559 void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
2560 {
2561         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2562         IDProperty *idprop;
2563
2564         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2565         BLI_assert(RNA_property_array_check(prop) == false);
2566         /* useful to check on bad values but set function should clamp */
2567         /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */
2568
2569         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2570                 RNA_property_float_clamp(ptr, prop, &value);
2571                 if (idprop->type == IDP_FLOAT)
2572                         IDP_Float(idprop) = value;
2573                 else
2574                         IDP_Double(idprop) = value;
2575
2576                 rna_idproperty_touch(idprop);
2577         }
2578         else if (fprop->set) {
2579                 fprop->set(ptr, value);
2580         }
2581         else if (fprop->set_ex) {
2582                 fprop->set_ex(ptr, prop, value);
2583         }
2584         else if (prop->flag & PROP_EDITABLE) {
2585                 IDPropertyTemplate val = {0};
2586                 IDProperty *group;
2587
2588                 RNA_property_float_clamp(ptr, prop, &value);
2589
2590                 val.f = value;
2591
2592                 group = RNA_struct_idprops(ptr, 1);
2593                 if (group)
2594                         IDP_AddToGroup(group, IDP_New(IDP_FLOAT, &val, prop->identifier));
2595         }
2596 }
2597
2598 void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
2599 {
2600         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2601         IDProperty *idprop;
2602         int i;
2603
2604         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2605         BLI_assert(RNA_property_array_check(prop) != false);
2606
2607         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2608                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2609                 if (prop->arraydimension == 0)
2610                         values[0] = RNA_property_float_get(ptr, prop);
2611                 else if (idprop->subtype == IDP_FLOAT) {
2612                         memcpy(values, IDP_Array(idprop), sizeof(float) * idprop->len);
2613                 }
2614                 else {
2615                         for (i = 0; i < idprop->len; i++)
2616                                 values[i] =  (float)(((double *)IDP_Array(idprop))[i]);
2617                 }
2618         }
2619         else if (prop->arraydimension == 0)
2620                 values[0] = RNA_property_float_get(ptr, prop);
2621         else if (fprop->getarray)
2622                 fprop->getarray(ptr, values);
2623         else if (fprop->getarray_ex)
2624                 fprop->getarray_ex(ptr, prop, values);
2625         else if (fprop->defaultarray)
2626                 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2627         else
2628                 memset(values, 0, sizeof(float) * prop->totarraylength);
2629 }
2630
2631 void RNA_property_float_get_array_range(PointerRNA *ptr, PropertyRNA *prop, float values[2])
2632 {
2633         const int array_len = RNA_property_array_length(ptr, prop);
2634
2635         if (array_len <= 0) {
2636                 values[0] = 0.0f;
2637                 values[1] = 0.0f;
2638         }
2639         else if (array_len == 1) {
2640                 RNA_property_float_get_array(ptr, prop, values);
2641                 values[1] = values[0];
2642         }
2643         else {
2644                 float arr_stack[32];
2645                 float *arr;
2646                 int i;
2647
2648                 if (array_len > 32) {
2649                         arr = MEM_mallocN(sizeof(float) * array_len, __func__);
2650                 }
2651                 else {
2652                         arr = arr_stack;
2653                 }
2654
2655                 RNA_property_float_get_array(ptr, prop, arr);
2656                 values[0] = values[1] = arr[0];
2657                 for (i = 1; i < array_len; i++) {
2658                         values[0] = MIN2(values[0], arr[i]);
2659                         values[1] = MAX2(values[1], arr[i]);
2660                 }
2661
2662                 if (arr != arr_stack) {
2663                         MEM_freeN(arr);
2664                 }
2665         }
2666 }
2667
2668 float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2669 {
2670         float tmp[RNA_MAX_ARRAY_LENGTH];
2671         int len = rna_ensure_property_array_length(ptr, prop);
2672
2673         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2674         BLI_assert(RNA_property_array_check(prop) != false);
2675         BLI_assert(index >= 0);
2676         BLI_assert(index < len);
2677
2678         if (len <= RNA_MAX_ARRAY_LENGTH) {
2679                 RNA_property_float_get_array(ptr, prop, tmp);
2680                 return tmp[index];
2681         }
2682         else {
2683                 float *tmparray, value;
2684
2685                 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2686                 RNA_property_float_get_array(ptr, prop, tmparray);
2687                 value = tmparray[index];
2688                 MEM_freeN(tmparray);
2689
2690                 return value;
2691         }
2692 }
2693
2694 void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
2695 {
2696         FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop;
2697         IDProperty *idprop;
2698         int i;
2699
2700         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2701         BLI_assert(RNA_property_array_check(prop) != false);
2702
2703         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2704                 BLI_assert(idprop->len == RNA_property_array_length(ptr, prop) || (prop->flag & PROP_IDPROPERTY));
2705                 if (prop->arraydimension == 0) {
2706                         if (idprop->type == IDP_FLOAT)
2707                                 IDP_Float(idprop) = values[0];
2708                         else
2709                                 IDP_Double(idprop) = values[0];
2710                 }
2711                 else if (idprop->subtype == IDP_FLOAT) {
2712                         memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2713                 }
2714                 else {
2715                         for (i = 0; i < idprop->len; i++)
2716                                 ((double *)IDP_Array(idprop))[i] = values[i];
2717                 }
2718
2719                 rna_idproperty_touch(idprop);
2720         }
2721         else if (prop->arraydimension == 0)
2722                 RNA_property_float_set(ptr, prop, values[0]);
2723         else if (fprop->setarray) {
2724                 fprop->setarray(ptr, values);
2725         }
2726         else if (fprop->setarray_ex) {
2727                 fprop->setarray_ex(ptr, prop, values);
2728         }
2729         else if (prop->flag & PROP_EDITABLE) {
2730                 IDPropertyTemplate val = {0};
2731                 IDProperty *group;
2732
2733                 /* TODO: RNA_property_float_clamp_array(ptr, prop, &value); */
2734
2735                 val.array.len = prop->totarraylength;
2736                 val.array.type = IDP_FLOAT;
2737
2738                 group = RNA_struct_idprops(ptr, 1);
2739                 if (group) {
2740                         idprop = IDP_New(IDP_ARRAY, &val, prop->identifier);
2741                         IDP_AddToGroup(group, idprop);
2742                         memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
2743                 }
2744         }
2745 }
2746
2747 void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, float value)
2748 {
2749         float tmp[RNA_MAX_ARRAY_LENGTH];
2750         int len = rna_ensure_property_array_length(ptr, prop);
2751
2752         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2753         BLI_assert(RNA_property_array_check(prop) != false);
2754         BLI_assert(index >= 0);
2755         BLI_assert(index < len);
2756
2757         if (len <= RNA_MAX_ARRAY_LENGTH) {
2758                 RNA_property_float_get_array(ptr, prop, tmp);
2759                 tmp[index] = value;
2760                 RNA_property_float_set_array(ptr, prop, tmp);
2761         }
2762         else {
2763                 float *tmparray;
2764
2765                 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2766                 RNA_property_float_get_array(ptr, prop, tmparray);
2767                 tmparray[index] = value;
2768                 RNA_property_float_set_array(ptr, prop, tmparray);
2769                 MEM_freeN(tmparray);
2770         }
2771 }
2772
2773 float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2774 {
2775         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
2776
2777         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2778         BLI_assert(RNA_property_array_check(prop) == false);
2779
2780         return fprop->defaultvalue;
2781 }
2782
2783 void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *prop, float *values)
2784 {
2785         FloatPropertyRNA *fprop = (FloatPropertyRNA *)rna_ensure_property(prop);
2786         
2787         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2788         BLI_assert(RNA_property_array_check(prop) != false);
2789
2790         if (prop->arraydimension == 0)
2791                 values[0] = fprop->defaultvalue;
2792         else if (fprop->defaultarray)
2793                 memcpy(values, fprop->defaultarray, sizeof(float) * prop->totarraylength);
2794         else
2795                 memset(values, 0, sizeof(float) * prop->totarraylength);
2796 }
2797
2798 float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int index)
2799 {
2800         float tmp[RNA_MAX_ARRAY_LENGTH];
2801         int len = rna_ensure_property_array_length(ptr, prop);
2802
2803         BLI_assert(RNA_property_type(prop) == PROP_FLOAT);
2804         BLI_assert(RNA_property_array_check(prop) != false);
2805         BLI_assert(index >= 0);
2806         BLI_assert(index < prop->totarraylength);
2807
2808         if (len <= RNA_MAX_ARRAY_LENGTH) {
2809                 RNA_property_float_get_default_array(ptr, prop, tmp);
2810                 return tmp[index];
2811         }
2812         else {
2813                 float *tmparray, value;
2814
2815                 tmparray = MEM_mallocN(sizeof(float) * len, __func__);
2816                 RNA_property_float_get_default_array(ptr, prop, tmparray);
2817                 value = tmparray[index];
2818                 MEM_freeN(tmparray);
2819
2820                 return value;
2821         }
2822 }
2823
2824 void RNA_property_string_get(PointerRNA *ptr, PropertyRNA *prop, char *value)
2825 {
2826         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2827         IDProperty *idprop;
2828
2829         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2830
2831         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2832                 /* editing bytes is not 100% supported
2833                  * since they can contain NIL chars */
2834                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2835                         memcpy(value, IDP_String(idprop), idprop->len);
2836                         value[idprop->len] = '\0';
2837                 }
2838                 else {
2839                         memcpy(value, IDP_String(idprop), idprop->len);
2840                 }
2841         }
2842         else if (sprop->get) {
2843                 sprop->get(ptr, value);
2844         }
2845         else if (sprop->get_ex) {
2846                 sprop->get_ex(ptr, prop, value);
2847         }
2848         else {
2849                 strcpy(value, sprop->defaultvalue);
2850         }
2851 }
2852
2853 char *RNA_property_string_get_alloc(PointerRNA *ptr, PropertyRNA *prop,
2854                                     char *fixedbuf, int fixedlen, int *r_len)
2855 {
2856         char *buf;
2857         int length;
2858
2859         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2860         if (!ptr->data) {
2861                 return NULL;
2862         }
2863
2864         length = RNA_property_string_length(ptr, prop);
2865
2866         if (length + 1 < fixedlen)
2867                 buf = fixedbuf;
2868         else
2869                 buf = MEM_mallocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
2870
2871 #ifndef NDEBUG
2872         /* safety check to ensure the string is actually set */
2873         buf[length] = 255;
2874 #endif
2875
2876         RNA_property_string_get(ptr, prop, buf);
2877
2878 #ifndef NDEBUG
2879         BLI_assert(buf[length] == '\0');
2880 #endif
2881
2882         if (r_len) {
2883                 *r_len = length;
2884         }
2885
2886         return buf;
2887 }
2888
2889 /* this is the length without \0 terminator */
2890 int RNA_property_string_length(PointerRNA *ptr, PropertyRNA *prop)
2891 {
2892         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2893         IDProperty *idprop;
2894
2895         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2896
2897         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2898                 if (idprop->subtype == IDP_STRING_SUB_BYTE) {
2899                         return idprop->len;
2900                 }
2901                 else {
2902 #ifndef NDEBUG
2903                         /* these _must_ stay in sync */
2904                         BLI_assert(strlen(IDP_String(idprop)) == idprop->len - 1);
2905 #endif
2906                         return idprop->len - 1;
2907                 }
2908         }
2909         else if (sprop->length)
2910                 return sprop->length(ptr);
2911         else if (sprop->length_ex)
2912                 return sprop->length_ex(ptr, prop);
2913         else
2914                 return strlen(sprop->defaultvalue);
2915 }
2916
2917 void RNA_property_string_set(PointerRNA *ptr, PropertyRNA *prop, const char *value)
2918 {
2919         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2920         IDProperty *idprop;
2921
2922         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2923
2924         if ((idprop = rna_idproperty_check(&prop, ptr))) {
2925                 /* both IDP_STRING_SUB_BYTE / IDP_STRING_SUB_UTF8 */
2926                 IDP_AssignString(idprop, value, RNA_property_string_maxlength(prop) - 1);
2927                 rna_idproperty_touch(idprop);
2928         }
2929         else if (sprop->set)
2930                 sprop->set(ptr, value);  /* set function needs to clamp its self */
2931         else if (sprop->set_ex)
2932                 sprop->set_ex(ptr, prop, value);  /* set function needs to clamp its self */
2933         else if (prop->flag & PROP_EDITABLE) {
2934                 IDProperty *group;
2935
2936                 group = RNA_struct_idprops(ptr, 1);
2937                 if (group)
2938                         IDP_AddToGroup(group, IDP_NewString(value, prop->identifier, RNA_property_string_maxlength(prop)));
2939         }
2940 }
2941
2942 void RNA_property_string_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop, char *value)
2943 {
2944         StringPropertyRNA *sprop = (StringPropertyRNA *)rna_ensure_property(prop);
2945
2946         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2947
2948         strcpy(value, sprop->defaultvalue);
2949 }
2950
2951 char *RNA_property_string_get_default_alloc(PointerRNA *ptr, PropertyRNA *prop, char *fixedbuf, int fixedlen)
2952 {
2953         char *buf;
2954         int length;
2955
2956         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2957
2958         length = RNA_property_string_default_length(ptr, prop);
2959
2960         if (length + 1 < fixedlen)
2961                 buf = fixedbuf;
2962         else
2963                 buf = MEM_callocN(sizeof(char) * (length + 1), "RNA_string_get_alloc");
2964
2965         RNA_property_string_get_default(ptr, prop, buf);
2966
2967         return buf;
2968 }
2969
2970 /* this is the length without \0 terminator */
2971 int RNA_property_string_default_length(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
2972 {
2973         StringPropertyRNA *sprop = (StringPropertyRNA *)prop;
2974
2975         BLI_assert(RNA_property_type(prop) == PROP_STRING);
2976
2977         return strlen(sprop->defaultvalue);
2978 }
2979
2980 int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
2981 {
2982         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
2983         IDProperty *idprop;
2984
2985         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
2986
2987         if ((idprop = rna_idproperty_check(&prop, ptr)))
2988                 return IDP_Int(idprop);
2989         else if (eprop->get)
2990                 return eprop->get(ptr);
2991         else if (eprop->get_ex)
2992                 return eprop->get_ex(ptr, prop);
2993         else
2994                 return eprop->defaultvalue;
2995 }
2996
2997 void RNA_property_enum_set(PointerRNA *ptr, PropertyRNA *prop, int value)
2998 {
2999         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3000         IDProperty *idprop;
3001
3002         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3003
3004         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3005                 IDP_Int(idprop) = value;
3006                 rna_idproperty_touch(idprop);
3007         }
3008         else if (eprop->set) {
3009                 eprop->set(ptr, value);
3010         }
3011         else if (eprop->set_ex) {
3012                 eprop->set_ex(ptr, prop, value);
3013         }
3014         else if (prop->flag & PROP_EDITABLE) {
3015                 IDPropertyTemplate val = {0};
3016                 IDProperty *group;
3017
3018                 val.i = value;
3019
3020                 group = RNA_struct_idprops(ptr, 1);
3021                 if (group)
3022                         IDP_AddToGroup(group, IDP_New(IDP_INT, &val, prop->identifier));
3023         }
3024 }
3025
3026 int RNA_property_enum_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
3027 {
3028         EnumPropertyRNA *eprop = (EnumPropertyRNA *)rna_ensure_property(prop);
3029
3030         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3031
3032         return eprop->defaultvalue;
3033 }
3034
3035 void *RNA_property_enum_py_data_get(PropertyRNA *prop)
3036 {
3037         EnumPropertyRNA *eprop = (EnumPropertyRNA *)prop;
3038
3039         BLI_assert(RNA_property_type(prop) == PROP_ENUM);
3040
3041         return eprop->py_data;
3042 }
3043
3044 /**
3045  * Get the value of the item that is \a step items away from \a from_value.
3046  *
3047  * \param from_value: Item value to start stepping from.
3048  * \param step: Absolute value defines step size, sign defines direction.
3049  *              E.g to get the next item, pass 1, for the previous -1.
3050  */
3051 int RNA_property_enum_step(const bContext *C, PointerRNA *ptr, PropertyRNA *prop, int from_value, int step)
3052 {
3053         EnumPropertyItem *item_array;
3054         int totitem;
3055         bool free;
3056         int result_value = from_value;
3057         int i, i_init;
3058         int single_step = (step < 0) ? -1 : 1;
3059         int step_tot = 0;
3060
3061         RNA_property_enum_items((bContext *)C, ptr, prop, &item_array, &totitem, &free);
3062         i = RNA_enum_from_value(item_array, from_value);
3063         i_init = i;
3064
3065         do {
3066                 i = mod_i(i + single_step, totitem);
3067                 if (item_array[i].identifier[0]) {
3068                         step_tot += single_step;
3069                 }
3070         } while ((i != i_init) && (step_tot != step));
3071
3072         if (i != i_init) {
3073                 result_value = item_array[i].value;
3074         }
3075
3076         if (free) {
3077                 MEM_freeN(item_array);
3078         }
3079
3080         return result_value;
3081 }
3082
3083 PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
3084 {
3085         PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3086         IDProperty *idprop;
3087
3088         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3089
3090         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3091                 pprop = (PointerPropertyRNA *)prop;
3092
3093                 if (RNA_struct_is_ID(pprop->type)) {
3094                         return rna_pointer_inherit_refine(ptr, pprop->type, IDP_Id(idprop));
3095                 }
3096
3097                 /* for groups, data is idprop itself */
3098                 if (pprop->typef)
3099                         return rna_pointer_inherit_refine(ptr, pprop->typef(ptr), idprop);
3100                 else
3101                         return rna_pointer_inherit_refine(ptr, pprop->type, idprop);
3102         }
3103         else if (pprop->get) {
3104                 return pprop->get(ptr);
3105         }
3106         else if (prop->flag & PROP_IDPROPERTY) {
3107                 /* XXX temporary hack to add it automatically, reading should
3108                  * never do any write ops, to ensure thread safety etc .. */
3109                 RNA_property_pointer_add(ptr, prop);
3110                 return RNA_property_pointer_get(ptr, prop);
3111         }
3112         else {
3113                 return PointerRNA_NULL;
3114         }
3115 }
3116
3117 void RNA_property_pointer_set(PointerRNA *ptr, PropertyRNA *prop, PointerRNA ptr_value)
3118 {
3119         PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop;
3120         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3121
3122         /* Check types */
3123         if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, pprop->type)) {
3124                 printf("%s: expected %s type, not %s.\n", __func__, pprop->type->identifier, ptr_value.type->identifier);
3125                 return;
3126         }
3127
3128         /* RNA */
3129         if (pprop->set &&
3130             !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
3131             !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data))
3132         {
3133                 pprop->set(ptr, ptr_value);
3134         }
3135         /* IDProperty */
3136         else if (prop->flag & PROP_EDITABLE) {
3137                 IDPropertyTemplate val = {0};
3138                 IDProperty *group;
3139
3140                 val.id = ptr_value.data;
3141
3142                 group = RNA_struct_idprops(ptr, true);
3143                 if (group) {
3144                         IDP_ReplaceInGroup(group, IDP_New(IDP_ID, &val, prop->identifier));
3145                 }
3146         }
3147 }
3148
3149 PointerRNA RNA_property_pointer_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop))
3150 {
3151         /*PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; */
3152
3153         /* BLI_assert(RNA_property_type(prop) == PROP_POINTER); */
3154
3155         return PointerRNA_NULL; /* FIXME: there has to be a way... */
3156 }
3157
3158 void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop)
3159 {
3160         /*IDProperty *idprop;*/
3161
3162         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3163
3164         if ((/*idprop=*/ rna_idproperty_check(&prop, ptr))) {
3165                 /* already exists */
3166         }
3167         else if (prop->flag & PROP_IDPROPERTY) {
3168                 IDPropertyTemplate val = {0};
3169                 IDProperty *group;
3170
3171                 val.i = 0;
3172
3173                 group = RNA_struct_idprops(ptr, 1);
3174                 if (group)
3175                         IDP_AddToGroup(group, IDP_New(IDP_GROUP, &val, prop->identifier));
3176         }
3177         else
3178                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
3179 }
3180
3181 void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop)
3182 {
3183         IDProperty *idprop, *group;
3184
3185         BLI_assert(RNA_property_type(prop) == PROP_POINTER);
3186
3187         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3188                 group = RNA_struct_idprops(ptr, 0);
3189                 
3190                 if (group) {
3191                         IDP_FreeFromGroup(group, idprop);
3192                 }
3193         }
3194         else
3195                 printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);
3196 }
3197
3198 static void rna_property_collection_get_idp(CollectionPropertyIterator *iter)
3199 {
3200         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)iter->prop;
3201
3202         iter->ptr.data = rna_iterator_array_get(iter);
3203         iter->ptr.type = cprop->item_type;
3204         rna_pointer_inherit_id(cprop->item_type, &iter->parent, &iter->ptr);
3205 }
3206
3207 void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
3208 {
3209         IDProperty *idprop;
3210
3211         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3212
3213         memset(iter, 0, sizeof(*iter));
3214
3215         if ((idprop = rna_idproperty_check(&prop, ptr)) || (prop->flag & PROP_IDPROPERTY)) {
3216                 iter->parent = *ptr;
3217                 iter->prop = prop;
3218
3219                 if (idprop)
3220                         rna_iterator_array_begin(iter, IDP_IDPArray(idprop), sizeof(IDProperty), idprop->len, 0, NULL);
3221                 else
3222                         rna_iterator_array_begin(iter, NULL, sizeof(IDProperty), 0, 0, NULL);
3223
3224                 if (iter->valid)
3225                         rna_property_collection_get_idp(iter);
3226
3227                 iter->idprop = 1;
3228         }
3229         else {
3230                 CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3231                 cprop->begin(iter, ptr);
3232         }
3233 }
3234
3235 void RNA_property_collection_next(CollectionPropertyIterator *iter)
3236 {
3237         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3238
3239         if (iter->idprop) {
3240                 rna_iterator_array_next(iter);
3241
3242                 if (iter->valid)
3243                         rna_property_collection_get_idp(iter);
3244         }
3245         else
3246                 cprop->next(iter);
3247 }
3248
3249 void RNA_property_collection_skip(CollectionPropertyIterator *iter, int num)
3250 {
3251         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3252         int i;
3253
3254         if (num > 1 && (iter->idprop || (cprop->property.flag_internal & PROP_INTERN_RAW_ARRAY))) {
3255                 /* fast skip for array */
3256                 ArrayIterator *internal = &iter->internal.array;
3257
3258                 if (!internal->skip) {
3259                         internal->ptr += internal->itemsize * (num - 1);
3260                         iter->valid = (internal->ptr < internal->endptr);
3261                         if (iter->valid)
3262                                 RNA_property_collection_next(iter);
3263                         return;
3264                 }
3265         }
3266
3267         /* slow iteration otherwise */
3268         for (i = 0; i < num && iter->valid; i++)
3269                 RNA_property_collection_next(iter);
3270 }
3271
3272 void RNA_property_collection_end(CollectionPropertyIterator *iter)
3273 {
3274         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)rna_ensure_property(iter->prop);
3275
3276         if (iter->idprop)
3277                 rna_iterator_array_end(iter);
3278         else
3279                 cprop->end(iter);
3280 }
3281
3282 int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop)
3283 {
3284         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3285         IDProperty *idprop;
3286
3287         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3288
3289         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3290                 return idprop->len;
3291         }
3292         else if (cprop->length) {
3293                 return cprop->length(ptr);
3294         }
3295         else {
3296                 CollectionPropertyIterator iter;
3297                 int length = 0;
3298
3299                 RNA_property_collection_begin(ptr, prop, &iter);
3300                 for (; iter.valid; RNA_property_collection_next(&iter))
3301                         length++;
3302                 RNA_property_collection_end(&iter);
3303
3304                 return length;
3305         }
3306 }
3307
3308 void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
3309 {
3310         IDProperty *idprop;
3311 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
3312
3313         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3314
3315         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3316                 IDPropertyTemplate val = {0};
3317                 IDProperty *item;
3318
3319                 item = IDP_New(IDP_GROUP, &val, "");
3320                 IDP_AppendArray(idprop, item);
3321                 /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory  */
3322                 MEM_freeN(item);
3323                 rna_idproperty_touch(idprop);
3324         }
3325         else if (prop->flag & PROP_IDPROPERTY) {
3326                 IDProperty *group, *item;
3327                 IDPropertyTemplate val = {0};
3328
3329                 group = RNA_struct_idprops(ptr, 1);
3330                 if (group) {
3331                         idprop = IDP_NewIDPArray(prop->identifier);
3332                         IDP_AddToGroup(group, idprop);
3333
3334                         item = IDP_New(IDP_GROUP, &val, "");
3335                         IDP_AppendArray(idprop, item);
3336                         /* IDP_FreeProperty(item);  *//* IDP_AppendArray does a shallow copy (memcpy), only free memory */
3337                         MEM_freeN(item);
3338                 }
3339         }
3340
3341         /* py api calls directly */
3342 #if 0
3343         else if (cprop->add) {
3344                 if (!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
3345                         ParameterList params;
3346                         RNA_parameter_list_create(&params, ptr, cprop->add);
3347                         RNA_function_call(NULL, NULL, ptr, cprop->add, &params);
3348                         RNA_parameter_list_free(&params);
3349                 }
3350         }
3351 #if 0
3352         else {
3353                 printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);
3354         }
3355 #endif
3356 #endif
3357
3358         if (r_ptr) {
3359                 if (idprop) {
3360                         CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop;
3361
3362                         r_ptr->data = IDP_GetIndexArray(idprop, idprop->len - 1);
3363                         r_ptr->type = cprop->item_type;
3364                         rna_pointer_inherit_id(NULL, ptr, r_ptr);
3365                 }
3366                 else
3367                         memset(r_ptr, 0, sizeof(*r_ptr));
3368         }
3369 }
3370
3371 bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key)
3372 {
3373         IDProperty *idprop;
3374 /*      CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */
3375
3376         BLI_assert(RNA_property_type(prop) == PROP_COLLECTION);
3377
3378         if ((idprop = rna_idproperty_check(&prop, ptr))) {
3379                 IDProperty tmp, *array;
3380                 int len;
3381
3382                 len = idprop->len;
3383                 array = IDP_IDPArray(idprop);
3384
3385                 if (key >= 0 && key < len) {
3386                         if (key + 1 < len) {
3387                                 /* move element to be removed to the back */
3388                                 memcpy(&tmp, &array[key], sizeof(IDProperty));
3389                                 memmove(array + key, array + key + 1, sizeof(IDProperty) * (len - (key + 1)));
3390                                 memcpy(&array[len - 1], &tmp, sizeof(IDProperty));
3391                         }
3392
3393                         IDP_ResizeIDPArray(idprop, len - 1);
3394                 }
3395
3396                 return true;
3397         }
3398         else if (prop->flag & PROP_IDPROPERTY) {
3399                 return true;
3400         }
3401
3402         /* py api calls directly */
3403 #if 0
3404         else if (cprop->remove) {
3405                 if (!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */
3406                         ParameterList params;
3407                         RNA_parameter_list_create(&params, ptr, cprop->remove);
3408                         RNA_function_call(NULL, NULL, ptr, cprop->remove, &params);
3409                         RNA_parameter_list_free(&params);
3410                 }
3411