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